diff --git a/__tests__/actions/profile.js b/__tests__/actions/profile.js
index 4ea366a3..b4d1848b 100644
--- a/__tests__/actions/profile.js
+++ b/__tests__/actions/profile.js
@@ -18,6 +18,8 @@ const linkedAccounts = [{
 
 // Mock services
 const mockMembersService = {
+  getPresignedUrl: jest.fn().mockReturnValue(Promise.resolve()),
+  uploadFileToS3: jest.fn().mockReturnValue(Promise.resolve()),
   updateMemberPhoto: jest.fn().mockReturnValue(Promise.resolve('url-of-photo')),
   updateMemberProfile: jest.fn().mockReturnValue(Promise.resolve(profile)),
   addSkill: jest.fn().mockReturnValue(Promise.resolve({ skills: [skill] })),
@@ -45,6 +47,8 @@ test('Module exports', () => expect(actions).toMatchSnapshot());
 test('profile.uploadPhotoDone', async () => {
   const actionResult = await redux.resolveAction(actions.profile.uploadPhotoDone(handle, tokenV3));
   expect(actionResult).toMatchSnapshot();
+  expect(mockMembersService.getPresignedUrl).toBeCalled();
+  expect(mockMembersService.uploadFileToS3).toBeCalled();
   expect(mockMembersService.updateMemberPhoto).toBeCalled();
 });
 
diff --git a/docs/services.members.md b/docs/services.members.md
index 8fe477f2..856b90ce 100644
--- a/docs/services.members.md
+++ b/docs/services.members.md
@@ -25,7 +25,9 @@ members via API V3.
             * [.addSkill(handle, skillTagId)](#module_services.members..MembersService+addSkill) ⇒ <code>Promise</code>
             * [.hideSkill(handle, skillTagId)](#module_services.members..MembersService+hideSkill) ⇒ <code>Promise</code>
             * [.updateMemberProfile(profile)](#module_services.members..MembersService+updateMemberProfile) ⇒ <code>Promise</code>
-            * [.updateMemberPhoto(userHandle, file)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
+            * [.getPresignedUrl(userHandle, file)](#module_services.members..MembersService+getPresignedUrl) ⇒ <code>Promise</code>
+            * [.updateMemberPhoto(S3Response)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
+            * [.uploadFileToS3(presignedUrlResponse)](#module_services.members..MembersService+uploadFileToS3) ⇒ <code>Promise</code>
            * [.verifyMemberNewEmail(handle, emailVerifyToken)](#module_services.members..MembersService+verifyMemberNewEmail) ⇒ <code>Promise</code>
 
 <a name="module_services.members.getService"></a>
@@ -63,7 +65,9 @@ Service class.
     * [.addSkill(handle, skillTagId)](#module_services.members..MembersService+addSkill) ⇒ <code>Promise</code>
     * [.hideSkill(handle, skillTagId)](#module_services.members..MembersService+hideSkill) ⇒ <code>Promise</code>
     * [.updateMemberProfile(profile)](#module_services.members..MembersService+updateMemberProfile) ⇒ <code>Promise</code>
-    * [.updateMemberPhoto(userHandle, file)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
+    * [.getPresignedUrl(userHandle, file)](#module_services.members..MembersService+getPresignedUrl) ⇒ <code>Promise</code>
+    * [.updateMemberPhoto(S3Response)](#module_services.members..MembersService+updateMemberPhoto) ⇒ <code>Promise</code>
+    * [.uploadFileToS3(presignedUrlResponse)](#module_services.members..MembersService+uploadFileToS3) ⇒ <code>Promise</code>
     * [.verifyMemberNewEmail(handle, emailVerifyToken)](#module_services.members..MembersService+verifyMemberNewEmail) ⇒ <code>Promise</code>
 
 <a name="new_module_services.members..MembersService_new"></a>
@@ -252,10 +256,10 @@ Updates member profile.
 | --- | --- | --- |
 | profile | <code>Object</code> | The profile to update. |
 
-<a name="module_services.members..MembersService+updateMemberPhoto"></a>
+<a name="module_services.members..MembersService+getPresignedUrl"></a>
 
-#### membersService.updateMemberPhoto(userHandle, file) ⇒ <code>Promise</code>
-Uploads and updates member photo.
+#### membersService.getPresignedUrl(userHandle, file) ⇒ <code>Promise</code>
+Gets presigned url for member photo file.
 
 **Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
 **Returns**: <code>Promise</code> - Resolves to the api response content
@@ -263,7 +267,31 @@ Uploads and updates member photo.
 | Param | Type | Description |
 | --- | --- | --- |
 | userHandle | <code>String</code> | The user handle |
-| file | <code>File</code> | The file to be uploaded |
+| file | <code>File</code> | The file to get its presigned url |
+
+<a name="module_services.members..MembersService+updateMemberPhoto"></a>
+
+#### membersService.updateMemberPhoto(S3Response) ⇒ <code>Promise</code>
+Updates member photo.
+
+**Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
+**Returns**: <code>Promise</code> - Resolves to the api response content
+
+| Param | Type | Description |
+| --- | --- | --- |
+| S3Response | <code>Object</code> | The response from uploadFileToS3() function. |
+
+<a name="module_services.members..MembersService+uploadFileToS3"></a>
+
+#### membersService.uploadFileToS3(presignedUrlResponse) ⇒ <code>Promise</code>
+Uploads file to S3.
+
+**Kind**: instance method of [<code>MembersService</code>](#module_services.members..MembersService)
+**Returns**: <code>Promise</code> - Resolves to the api response content
+
+| Param | Type | Description |
+| --- | --- | --- |
+| presignedUrlResponse | <code>Object</code> | The presigned url response from                                      getPresignedUrl() function. |
 
 <a name="module_services.members..MembersService+verifyMemberNewEmail"></a>
 
diff --git a/package.json b/package.json
index 7ab753e2..b1bf9678 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
     "lint:js": "./node_modules/.bin/eslint --ext .js,.jsx .",
     "test": "npm run lint && npm run jest"
   },
-  "version": "1.2.3",
+  "version": "1.2.2",
   "dependencies": {
     "auth0-js": "^6.8.4",
     "config": "^3.2.0",
diff --git a/src/actions/profile.js b/src/actions/profile.js
index 96a9ef5e..bcd668cf 100644
--- a/src/actions/profile.js
+++ b/src/actions/profile.js
@@ -216,7 +216,9 @@ function uploadPhotoInit() {}
  */
 function uploadPhotoDone(handle, tokenV3, file) {
   const service = getMembersService(tokenV3);
-  return service.updateMemberPhoto(handle, file)
+  return service.getPresignedUrl(handle, file)
+    .then(res => service.uploadFileToS3(res))
+    .then(res => service.updateMemberPhoto(res))
     .then(photoURL => ({ handle, photoURL }));
 }
 
diff --git a/src/services/members.js b/src/services/members.js
index 61f3e9ab..7b6648b0 100644
--- a/src/services/members.js
+++ b/src/services/members.js
@@ -4,10 +4,11 @@
  * members via API V3.
  */
 
-/* global FormData */
+/* global XMLHttpRequest */
 import _ from 'lodash';
 import qs from 'qs';
 import { decodeToken } from '@topcoder-platform/tc-auth-lib';
+import logger from '../utils/logger';
 import { getApiResponsePayload, handleApiResponse } from '../utils/tc';
 import { getApi } from './api';
 
@@ -238,23 +239,72 @@ class MembersService {
   }
 
   /**
-   * Updates member photo.
+   * Gets presigned url for member photo file.
    * @param {String} userHandle The user handle
-   * @param {File} file The photo to upload
+   * @param {File} file The file to get its presigned url
    * @return {Promise} Resolves to the api response content
    */
-  async updateMemberPhoto(userHandle, file) {
-    const formData = new FormData();
-    formData.append('photo', file);
-    const res = await this.private.apiV5.fetch(`/members/${userHandle}/photo`, {
-      method: 'POST',
-      headers: {
-        'Content-Type': null,
-      },
-      body: formData,
+  async getPresignedUrl(userHandle, file) {
+    const res = await this.private.api.postJson(`/members/${userHandle}/photoUploadUrl`, { param: { contentType: file.type } });
+    const payload = await getApiResponsePayload(res);
+
+    return {
+      preSignedURL: payload.preSignedURL,
+      token: payload.token,
+      file,
+      userHandle,
+    };
+  }
+
+  /**
+   * Updates member photo.
+   * @param {Object} S3Response The response from uploadFileToS3() function.
+   * @return {Promise} Resolves to the api response content
+   */
+  async updateMemberPhoto(S3Response) {
+    const res = await this.private.api.putJson(`/members/${S3Response.userHandle}/photo`, { param: S3Response.body });
+    return getApiResponsePayload(res);
+  }
+
+  /**
+   * Uploads file to S3.
+   * @param {Object} presignedUrlResponse The presigned url response from
+   *                                      getPresignedUrl() function.
+   * @return {Promise} Resolves to the api response content
+   */
+  uploadFileToS3(presignedUrlResponse) {
+    _.noop(this);
+    return new Promise((resolve, reject) => {
+      const xhr = new XMLHttpRequest();
+
+      xhr.open('PUT', presignedUrlResponse.preSignedURL, true);
+      xhr.setRequestHeader('Content-Type', presignedUrlResponse.file.type);
+
+      xhr.onreadystatechange = () => {
+        const { status } = xhr;
+        if (((status >= 200 && status < 300) || status === 304) && xhr.readyState === 4) {
+          resolve({
+            userHandle: presignedUrlResponse.userHandle,
+            body: {
+              token: presignedUrlResponse.token,
+              contentType: presignedUrlResponse.file.type,
+            },
+          });
+        } else if (status >= 400) {
+          const err = new Error('Could not upload image to S3');
+          err.status = status;
+          reject(err);
+        }
+      };
+
+      xhr.onerror = (err) => {
+        logger.error('Could not upload image to S3', err);
+
+        reject(err);
+      };
+
+      xhr.send(presignedUrlResponse.file);
     });
-    return handleApiResponse(res)
-      .then(({ photoURL }) => photoURL);
   }
 
   /**
diff --git a/src/services/user-traits.js b/src/services/user-traits.js
index 34d25a26..c1d71b71 100644
--- a/src/services/user-traits.js
+++ b/src/services/user-traits.js
@@ -4,7 +4,7 @@
  * via API V3.
  */
 import toCapitalCase from 'to-capital-case';
-import { handleApiResponse } from '../utils/tc';
+import { getApiResponsePayload } from '../utils/tc';
 import { getApi } from './api';
 
 /**
@@ -16,7 +16,7 @@ class UserTraitsService {
    */
   constructor(tokenV3) {
     this.private = {
-      api: getApi('V5', tokenV3),
+      api: getApi('V3', tokenV3),
       tokenV3,
     };
   }
@@ -29,7 +29,7 @@ class UserTraitsService {
   async getAllUserTraits(handle) {
     // FIXME: Remove the .toLowerCase() when the API is fixed to ignore the case in the route params
     const res = await this.private.api.get(`/members/${handle.toLowerCase()}/traits`);
-    return handleApiResponse(res);
+    return getApiResponsePayload(res);
   }
 
   /**
@@ -40,16 +40,18 @@ class UserTraitsService {
    * @return {Promise} Resolves to the member traits.
    */
   async addUserTrait(handle, traitId, data) {
-    const body = [{
-      traitId,
-      categoryName: toCapitalCase(traitId),
-      traits: {
-        data,
-      },
-    }];
+    const body = {
+      param: [{
+        traitId,
+        categoryName: toCapitalCase(traitId),
+        traits: {
+          data,
+        },
+      }],
+    };
 
     const res = await this.private.api.postJson(`/members/${handle}/traits`, body);
-    return handleApiResponse(res);
+    return getApiResponsePayload(res);
   }
 
   /**
@@ -60,16 +62,18 @@ class UserTraitsService {
    * @return {Promise} Resolves to the member traits.
    */
   async updateUserTrait(handle, traitId, data) {
-    const body = [{
-      traitId,
-      categoryName: toCapitalCase(traitId),
-      traits: {
-        data,
-      },
-    }];
+    const body = {
+      param: [{
+        traitId,
+        categoryName: toCapitalCase(traitId),
+        traits: {
+          data,
+        },
+      }],
+    };
 
     const res = await this.private.api.putJson(`/members/${handle}/traits`, body);
-    return handleApiResponse(res);
+    return getApiResponsePayload(res);
   }
 
   /**
@@ -80,7 +84,7 @@ class UserTraitsService {
    */
   async deleteUserTrait(handle, traitId) {
     const res = await this.private.api.delete(`/members/${handle}/traits?traitIds=${traitId}`);
-    return handleApiResponse(res);
+    return getApiResponsePayload(res);
   }
 }
 
diff --git a/src/utils/tc.js b/src/utils/tc.js
index ff6d46f1..2941de37 100644
--- a/src/utils/tc.js
+++ b/src/utils/tc.js
@@ -87,8 +87,7 @@ export async function getApiResponsePayload(res, shouldThrowError = true) {
  */
 export function handleApiResponse(response) {
   if (!response.ok) throw new Error(response.statusText);
-  return response.json()
-    .catch(() => null);
+  return response.json();
 }
 
 /**