diff --git a/__tests__/__snapshots__/index.js.snap b/__tests__/__snapshots__/index.js.snap
index 7bc989b4..f696ddae 100644
--- a/__tests__/__snapshots__/index.js.snap
+++ b/__tests__/__snapshots__/index.js.snap
@@ -291,6 +291,7 @@ Object {
       "getApiV4": [Function],
       "getApiV5": [Function],
       "getTcM2mToken": [Function],
+      "proxyApi": [Function],
     },
     "billing": Object {
       "default": [Function],
diff --git a/src/services/api.js b/src/services/api.js
index 4530a4a3..fffbc7c9 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -290,3 +290,21 @@ export async function getTcM2mToken() {
   const token = await m2m.getMachineToken(TC_M2M.CLIENT_ID, TC_M2M.CLIENT_SECRET);
   return token;
 }
+
+/**
+ * Call API via proxy
+ *
+ * @param {String} url  to API endpoint
+ */
+export async function proxyApi(endpoint) {
+  let domain = '';
+  if (isomorphy.isServerSide()) {
+    domain = `http://${config.ENV.HOST || 'localhost'}:${config.ENV.PORT || 3000}`;
+  }
+  const url = `${domain}/community-app-assets/api${endpoint}`;
+  let res = await fetch(url);
+  if (!res.ok) throw new Error(res.statusText);
+  res = (await res.json());
+  if (res.message) throw new Error(res.message);
+  return res;
+}
diff --git a/src/services/challenges.js b/src/services/challenges.js
index 10f0ded0..f16a8a33 100644
--- a/src/services/challenges.js
+++ b/src/services/challenges.js
@@ -11,7 +11,7 @@ import { decodeToken } from 'tc-accounts';
 import logger from '../utils/logger';
 import { setErrorIcon, ERROR_ICON_TYPES } from '../utils/errors';
 import { COMPETITION_TRACKS, getApiResponsePayload } from '../utils/tc';
-import { getApi } from './api';
+import { getApi, proxyApi } from './api';
 import { getService as getMembersService } from './members';
 
 export const ORDER_BY = {
@@ -200,6 +200,7 @@ class ChallengesService {
       apiV3: getApi('V3', tokenV3),
       getChallenges,
       getMemberChallenges,
+      proxyApi,
       tokenV2,
       tokenV3,
       memberService: getMembersService(),
@@ -325,27 +326,32 @@ class ChallengesService {
    * @return {Promise} Resolves to the challenge object.
    */
   async getChallengeDetails(challengeId) {
+    let challenge = {};
     let isLegacyChallenge = false;
-    const filters = {};
     // condition based on ROUTE used for Review Opportunities, change if needed
-    if (challengeId.length >= 5 && challengeId.length <= 8) {
+    if (/^[\d]{5,8}$/.test(challengeId)) {
       isLegacyChallenge = true;
-      filters.legacyId = challengeId;
+      challenge = await this.private.getChallenges('/challenges/', { legacyId: challengeId })
+        .then(res => res.challenges[0]);
     } else {
-      filters.id = challengeId;
+      challenge = await this.private.getChallenges(`/challenges/${challengeId}`)
+        .then(res => res.challenges);
     }
-    const challengeFiltered = await this.private.getChallenges('/challenges/', filters)
-      .then(res => res.challenges[0]);
-
-    if (challengeFiltered) {
-      challengeFiltered.isLegacyChallenge = isLegacyChallenge;
-      challengeFiltered.events = _.map(challengeFiltered.events, e => ({
-        eventName: e.key,
-        eventId: e.id,
-        description: e.name,
-      }));
-    }
-    return challengeFiltered;
+
+    const registrants = await this.getChallengeRegistrants(challenge.id);
+    challenge.registrants = registrants;
+
+    challenge.isLegacyChallenge = isLegacyChallenge;
+
+    challenge.events = _.map(challenge.events, e => ({
+      eventName: e.key,
+      eventId: e.id,
+      description: e.name,
+    }));
+
+    challenge.fetchedWithAuth = Boolean(this.private.apiV5.private.token);
+
+    return challenge;
   }
 
   /**
@@ -354,8 +360,7 @@ class ChallengesService {
    * @return {Promise} Resolves to the challenge registrants array.
    */
   async getChallengeRegistrants(challengeId) {
-    const registrants = await this.private.apiV5.get(`/resources/challengeId=${challengeId}`)
-      .then(checkError).then(res => res);
+    const registrants = await this.private.proxyApi(`/challenges/${challengeId}/registrants`);
     return registrants || [];
   }
 
@@ -518,19 +523,17 @@ class ChallengesService {
    * @param {String} roleName
    * @return {Promise}
    */
-  async getResourceRoleId(roleName) {
+  async getRoleId(roleName) {
     const params = {
       name: roleName,
-      isActive: true,
     };
-    const roles = await this.private.apiV5.get(`/resource-roles?${qs.stringify(params)}`)
-      .then(checkErrorV5).then(res => res);
+    const roles = await this.private.proxyApi(`/challenges/roleId?${qs.stringify(params)}`);
 
-    if (_.isEmpty(roles.result)) {
+    if (_.isEmpty(roles)) {
       throw new Error('Resource Role not found!');
     }
 
-    return roles.result[0].id;
+    return roles[0].id;
   }
 
   /**
@@ -540,7 +543,7 @@ class ChallengesService {
    */
   async register(challengeId) {
     const user = decodeToken(this.private.tokenV3);
-    const roleId = await this.getResourceRoleId('Submitter');
+    const roleId = await this.getRoleId('Submitter');
     const params = {
       challengeId,
       memberHandle: user.handle,
@@ -558,13 +561,13 @@ class ChallengesService {
    */
   async unregister(challengeId) {
     const user = decodeToken(this.private.tokenV3);
-    const roleId = await this.getResourceRoleId('Submitter');
+    const roleId = await this.getRoleId('Submitter');
     const params = {
       challengeId,
       memberHandle: user.handle,
       roleId,
     };
-    const res = await this.private.apiV5.delete('/resources', params);
+    const res = await this.private.apiV5.delete('/resources', JSON.stringify(params));
     if (!res.ok) throw new Error(res.statusText);
     return res.json();
   }