diff --git a/src/components/image_cropper/image_cropper.js b/src/components/image_cropper/image_cropper.js
index 5ba8f04e..01361e25 100644
--- a/src/components/image_cropper/image_cropper.js
+++ b/src/components/image_cropper/image_cropper.js
@@ -70,22 +70,10 @@ const ImageCropper = {
       this.dataUrl = undefined
       this.$emit('close')
     },
-    submit () {
+    submit (cropping = true) {
       this.submitting = true
       this.avatarUploadError = null
-      this.submitHandler(this.cropper, this.file)
-        .then(() => this.destroy())
-        .catch((err) => {
-          this.submitError = err
-        })
-        .finally(() => {
-          this.submitting = false
-        })
-    },
-    submitWithoutCropping () {
-      this.submitting = true
-      this.avatarUploadError = null
-      this.submitHandler(false, this.dataUrl)
+      this.submitHandler(cropping && this.cropper, this.file)
         .then(() => this.destroy())
         .catch((err) => {
           this.submitError = err
diff --git a/src/components/image_cropper/image_cropper.vue b/src/components/image_cropper/image_cropper.vue
index 129e6f46..d2b86e9e 100644
--- a/src/components/image_cropper/image_cropper.vue
+++ b/src/components/image_cropper/image_cropper.vue
@@ -5,9 +5,9 @@
         <img ref="img" :src="dataUrl" alt="" @load.stop="createCropper" />
       </div>
       <div class="image-cropper-buttons-wrapper">
-        <button class="btn" type="button" :disabled="submitting" @click="submit" v-text="saveText"></button>
+        <button class="btn" type="button" :disabled="submitting" @click="submit()" v-text="saveText"></button>
         <button class="btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText"></button>
-        <button class="btn" type="button" :disabled="submitting" @click="submitWithoutCropping" v-text="saveWithoutCroppingText"></button>
+        <button class="btn" type="button" :disabled="submitting" @click="submit(false)" v-text="saveWithoutCroppingText"></button>
         <i class="icon-spin4 animate-spin" v-if="submitting"></i>
       </div>
       <div class="alert error" v-if="submitError">
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 748f23f7..2418450c 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -109,37 +109,23 @@ const UserSettings = {
   },
   methods: {
     updateProfile () {
-      const name = this.newName
-      const description = this.newBio
-      const locked = this.newLocked
-      // Backend notation.
-      /* eslint-disable camelcase */
-      const default_scope = this.newDefaultScope
-      const no_rich_text = this.newNoRichText
-      const hide_follows = this.hideFollows
-      const hide_followers = this.hideFollowers
-      const show_role = this.showRole
-
-      /* eslint-enable camelcase */
       this.$store.state.api.backendInteractor
         .updateProfile({
           params: {
-            name,
-            description,
-            locked,
+            note: this.newBio,
+            locked: this.newLocked,
             // Backend notation.
             /* eslint-disable camelcase */
-            default_scope,
-            no_rich_text,
-            hide_follows,
-            hide_followers,
-            show_role
+            display_name: this.newName,
+            default_scope: this.newDefaultScope,
+            no_rich_text: this.newNoRichText,
+            hide_follows: this.hideFollows,
+            hide_followers: this.hideFollowers,
+            show_role: this.showRole
             /* eslint-enable camelcase */
           }}).then((user) => {
-            if (!user.error) {
-              this.$store.commit('addNewUsers', [user])
-              this.$store.commit('setCurrentUser', user)
-            }
+            this.$store.commit('addNewUsers', [user])
+            this.$store.commit('setCurrentUser', user)
           })
     },
     changeVis (visibility) {
@@ -159,23 +145,29 @@ const UserSettings = {
       reader.onload = ({target}) => {
         const img = target.result
         this[slot + 'Preview'] = img
+        this[slot] = file
       }
       reader.readAsDataURL(file)
     },
     submitAvatar (cropper, file) {
-      let img
-      if (cropper) {
-        img = cropper.getCroppedCanvas().toDataURL(file.type)
-      } else {
-        img = file
-      }
+      const that = this
+      return new Promise((resolve, reject) => {
+        function updateAvatar (avatar) {
+          that.$store.state.api.backendInteractor.updateAvatar({ avatar })
+            .then((user) => {
+              that.$store.commit('addNewUsers', [user])
+              that.$store.commit('setCurrentUser', user)
+              resolve()
+            })
+            .catch((err) => {
+              reject(new Error(that.$t('upload.error.base') + ' ' + err.message))
+            })
+        }
 
-      return this.$store.state.api.backendInteractor.updateAvatar({ params: { img } }).then((user) => {
-        if (!user.error) {
-          this.$store.commit('addNewUsers', [user])
-          this.$store.commit('setCurrentUser', user)
+        if (cropper) {
+          cropper.getCroppedCanvas().toBlob(updateAvatar, file.type)
         } else {
-          throw new Error(this.$t('upload.error.base') + user.error)
+          updateAvatar(file)
         }
       })
     },
@@ -185,30 +177,17 @@ const UserSettings = {
     submitBanner () {
       if (!this.bannerPreview) { return }
 
-      let banner = this.bannerPreview
-      // eslint-disable-next-line no-undef
-      let imginfo = new Image()
-      /* eslint-disable camelcase */
-      let offset_top, offset_left, width, height
-      imginfo.src = banner
-      width = imginfo.width
-      height = imginfo.height
-      offset_top = 0
-      offset_left = 0
       this.bannerUploading = true
-      this.$store.state.api.backendInteractor.updateBanner({params: {banner, offset_top, offset_left, width, height}}).then((data) => {
-        if (!data.error) {
-          let clone = JSON.parse(JSON.stringify(this.$store.state.users.currentUser))
-          clone.cover_photo = data.url
-          this.$store.commit('addNewUsers', [clone])
-          this.$store.commit('setCurrentUser', clone)
+      this.$store.state.api.backendInteractor.updateBanner({banner: this.banner})
+        .then((user) => {
+          this.$store.commit('addNewUsers', [user])
+          this.$store.commit('setCurrentUser', user)
           this.bannerPreview = null
-        } else {
-          this.bannerUploadError = this.$t('upload.error.base') + data.error
-        }
-        this.bannerUploading = false
-      })
-      /* eslint-enable camelcase */
+        })
+        .catch((err) => {
+          this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message
+        })
+        .then(() => { this.bannerUploading = false })
     },
     submitBg () {
       if (!this.backgroundPreview) { return }
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index a6892959..6d789f47 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -3,10 +3,7 @@ const LOGIN_URL = '/api/account/verify_credentials.json'
 const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing'
 const MENTIONS_URL = '/api/statuses/mentions.json'
 const REGISTRATION_URL = '/api/account/register.json'
-const AVATAR_UPDATE_URL = '/api/qvitter/update_avatar.json'
 const BG_UPDATE_URL = '/api/qvitter/update_background_image.json'
-const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json'
-const PROFILE_UPDATE_URL = '/api/account/update_profile.json'
 const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json'
 const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json'
 const BLOCKS_IMPORT_URL = '/api/pleroma/blocks_import'
@@ -50,6 +47,7 @@ const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
 const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
 const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
 const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
+const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials'
 
 import { each, map, concat, last } from 'lodash'
 import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
@@ -79,28 +77,16 @@ const promisedRequest = (url, options) => {
     })
 }
 
-// Params
-// cropH
-// cropW
-// cropX
-// cropY
-// img (base 64 encodend data url)
-const updateAvatar = ({credentials, params}) => {
-  let url = AVATAR_UPDATE_URL
-
+const updateAvatar = ({credentials, avatar}) => {
   const form = new FormData()
-
-  each(params, (value, key) => {
-    if (value) {
-      form.append(key, value)
-    }
-  })
-
-  return fetch(url, {
+  form.append('avatar', avatar)
+  return fetch(MASTODON_PROFILE_UPDATE_URL, {
     headers: authHeaders(credentials),
-    method: 'POST',
+    method: 'PATCH',
     body: form
-  }).then((data) => data.json())
+  })
+  .then((data) => data.json())
+  .then((data) => parseUser(data))
 }
 
 const updateBg = ({credentials, params}) => {
@@ -121,52 +107,29 @@ const updateBg = ({credentials, params}) => {
   }).then((data) => data.json())
 }
 
-// Params
-// height
-// width
-// offset_left
-// offset_top
-// banner (base 64 encodend data url)
-const updateBanner = ({credentials, params}) => {
-  let url = BANNER_UPDATE_URL
-
+const updateBanner = ({credentials, banner}) => {
   const form = new FormData()
-
-  each(params, (value, key) => {
-    if (value) {
-      form.append(key, value)
-    }
-  })
-
-  return fetch(url, {
+  form.append('header', banner)
+  return fetch(MASTODON_PROFILE_UPDATE_URL, {
     headers: authHeaders(credentials),
-    method: 'POST',
+    method: 'PATCH',
     body: form
-  }).then((data) => data.json())
+  })
+  .then((data) => data.json())
+  .then((data) => parseUser(data))
 }
 
-// Params
-// name
-// url
-// location
-// description
 const updateProfile = ({credentials, params}) => {
-  // Always include these fields, because they might be empty or false
-  const fields = ['description', 'locked', 'no_rich_text', 'hide_follows', 'hide_followers', 'show_role']
-  let url = PROFILE_UPDATE_URL
-
-  const form = new FormData()
-
-  each(params, (value, key) => {
-    if (fields.includes(key) || value) {
-      form.append(key, value)
-    }
+  return promisedRequest(MASTODON_PROFILE_UPDATE_URL, {
+    headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json',
+      ...authHeaders(credentials)
+    },
+    method: 'PATCH',
+    body: JSON.stringify(params)
   })
-  return fetch(url, {
-    headers: authHeaders(credentials),
-    method: 'POST',
-    body: form
-  }).then((data) => data.json())
+  .then((data) => parseUser(data))
 }
 
 // Params needed:
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 3256a921..b6f070fe 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -101,9 +101,9 @@ const backendInteractorService = (credentials) => {
 
   const getCaptcha = () => apiService.getCaptcha()
   const register = (params) => apiService.register(params)
-  const updateAvatar = ({params}) => apiService.updateAvatar({credentials, params})
+  const updateAvatar = ({avatar}) => apiService.updateAvatar({credentials, avatar})
   const updateBg = ({params}) => apiService.updateBg({credentials, params})
-  const updateBanner = ({params}) => apiService.updateBanner({credentials, params})
+  const updateBanner = ({banner}) => apiService.updateBanner({credentials, banner})
   const updateProfile = ({params}) => apiService.updateProfile({credentials, params})
 
   const externalProfile = (profileUrl) => apiService.externalProfile({profileUrl, credentials})