diff --git a/common/djangoapps/course_modes/api.py b/common/djangoapps/course_modes/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dce97f412c533439c2bf65d897080f0f999f9a6
--- /dev/null
+++ b/common/djangoapps/course_modes/api.py
@@ -0,0 +1,17 @@
+"""
+Python APIs exposed by the course_modes app to other in-process apps.
+"""
+
+from course_modes.models import CourseMode as _CourseMode
+
+
+def get_paid_modes_for_course(course_run_id):
+    """
+    Returns a list of non-expired mode slugs for a course run ID that have a set minimum price.
+
+    Params:
+        course_run_id (CourseKey): The course run you want to get the paid modes for
+    Returns:
+        A list of paid modes (strings) that the course has attached to it.
+    """
+    return _CourseMode.paid_modes_for_course(course_run_id)
diff --git a/common/djangoapps/course_modes/api/urls.py b/common/djangoapps/course_modes/api/urls.py
deleted file mode 100644
index e4cf046defbb601002c0900aae9d2467f2701ae2..0000000000000000000000000000000000000000
--- a/common/djangoapps/course_modes/api/urls.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""
-URL definitions for the course_modes API.
-"""
-
-
-from django.conf.urls import include, url
-
-app_name = 'common.djangoapps.course_modes.api'
-
-urlpatterns = [
-    url(r'^v1/', include('course_modes.api.v1.urls', namespace='v1')),
-]
diff --git a/common/djangoapps/course_modes/api/__init__.py b/common/djangoapps/course_modes/rest_api/__init__.py
similarity index 100%
rename from common/djangoapps/course_modes/api/__init__.py
rename to common/djangoapps/course_modes/rest_api/__init__.py
diff --git a/common/djangoapps/course_modes/api/serializers.py b/common/djangoapps/course_modes/rest_api/serializers.py
similarity index 100%
rename from common/djangoapps/course_modes/api/serializers.py
rename to common/djangoapps/course_modes/rest_api/serializers.py
diff --git a/common/djangoapps/course_modes/rest_api/urls.py b/common/djangoapps/course_modes/rest_api/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..349efb8a3f25d78d3c87db8d37ee048edd3065d9
--- /dev/null
+++ b/common/djangoapps/course_modes/rest_api/urls.py
@@ -0,0 +1,12 @@
+"""
+URL definitions for the course_modes API.
+"""
+
+
+from django.conf.urls import include, url
+
+app_name = 'common.djangoapps.course_modes.rest_api'
+
+urlpatterns = [
+    url(r'^v1/', include('course_modes.rest_api.v1.urls', namespace='v1')),
+]
diff --git a/common/djangoapps/course_modes/api/v1/__init__.py b/common/djangoapps/course_modes/rest_api/v1/__init__.py
similarity index 100%
rename from common/djangoapps/course_modes/api/v1/__init__.py
rename to common/djangoapps/course_modes/rest_api/v1/__init__.py
diff --git a/common/djangoapps/course_modes/api/v1/tests/__init__.py b/common/djangoapps/course_modes/rest_api/v1/tests/__init__.py
similarity index 100%
rename from common/djangoapps/course_modes/api/v1/tests/__init__.py
rename to common/djangoapps/course_modes/rest_api/v1/tests/__init__.py
diff --git a/common/djangoapps/course_modes/api/v1/tests/test_views.py b/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py
similarity index 99%
rename from common/djangoapps/course_modes/api/v1/tests/test_views.py
rename to common/djangoapps/course_modes/rest_api/v1/tests/test_views.py
index da5b881b80acae894e85ba9e1afc6bc9aa6ff28a..8a079f9bbd260d6208891fd00b014d74c0d6e9d9 100644
--- a/common/djangoapps/course_modes/api/v1/tests/test_views.py
+++ b/common/djangoapps/course_modes/rest_api/v1/tests/test_views.py
@@ -5,7 +5,6 @@ Tests for the course modes API.
 
 import json
 import unittest
-from itertools import product
 
 import ddt
 from django.conf import settings
@@ -15,7 +14,7 @@ from rest_framework import status
 from rest_framework.test import APITestCase
 from six import text_type
 
-from course_modes.api.v1.views import CourseModesView
+from course_modes.rest_api.v1.views import CourseModesView
 from course_modes.models import CourseMode
 from course_modes.tests.factories import CourseModeFactory
 from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
@@ -79,7 +78,7 @@ class CourseModesViewTestBase(AuthAndScopesTestMixin):
         """
         Required method to implement AuthAndScopesTestMixin.
         """
-        pass
+        pass  # pylint: disable=unnecessary-pass
 
     @ddt.data(*JWT_AUTH_TYPES)
     def test_jwt_on_behalf_of_user(self, auth_type):
diff --git a/common/djangoapps/course_modes/api/v1/urls.py b/common/djangoapps/course_modes/rest_api/v1/urls.py
similarity index 92%
rename from common/djangoapps/course_modes/api/v1/urls.py
rename to common/djangoapps/course_modes/rest_api/v1/urls.py
index 8933b3a4ac616cc2b2785df9a51db48cf0830d66..7dd28e36fdd266271c908fbf49362bd2a4de254d 100644
--- a/common/djangoapps/course_modes/api/v1/urls.py
+++ b/common/djangoapps/course_modes/rest_api/v1/urls.py
@@ -6,7 +6,7 @@ URL definitions for the course_modes v1 API.
 from django.conf import settings
 from django.conf.urls import url
 
-from course_modes.api.v1 import views
+from course_modes.rest_api.v1 import views
 
 app_name = 'v1'
 
diff --git a/common/djangoapps/course_modes/api/v1/views.py b/common/djangoapps/course_modes/rest_api/v1/views.py
similarity index 99%
rename from common/djangoapps/course_modes/api/v1/views.py
rename to common/djangoapps/course_modes/rest_api/v1/views.py
index 056bc103324a67659d3093340b7b127bd66a2174..e8d963e986ded243949f15377d7989f57b203dd8 100644
--- a/common/djangoapps/course_modes/api/v1/views.py
+++ b/common/djangoapps/course_modes/rest_api/v1/views.py
@@ -14,7 +14,7 @@ from rest_framework import status
 from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
 from rest_framework.response import Response
 
-from course_modes.api.serializers import CourseModeSerializer
+from course_modes.rest_api.serializers import CourseModeSerializer
 from course_modes.models import CourseMode
 from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
 from openedx.core.lib.api.parsers import MergePatchParser
diff --git a/lms/urls.py b/lms/urls.py
index 9e2c8b856733067f86b21a2a021cbcc1e2a1af55..93a00d1be3b5da4a1459a763d908ede8ac095418 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -156,8 +156,9 @@ urlpatterns = [
 
     # Multiple course modes and identity verification
     url(r'^course_modes/', include('course_modes.urls')),
-    url(r'^api/course_modes/', include(('course_modes.api.urls', 'common.djangoapps.course_mods'),
+    url(r'^api/course_modes/', include(('course_modes.rest_api.urls', 'common.djangoapps.course_mods'),
                                        namespace='course_modes_api')),
+
     url(r'^verify_student/', include('verify_student.urls')),
 
     # URLs for managing dark launches of languages
diff --git a/openedx/core/djangoapps/catalog/api.py b/openedx/core/djangoapps/catalog/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..74d6b5480403632d02ad184fbc94ae1f95a2423f
--- /dev/null
+++ b/openedx/core/djangoapps/catalog/api.py
@@ -0,0 +1,21 @@
+"""
+Python APIs exposed by the catalog app to other in-process apps.
+"""
+
+from .utils import get_programs_by_type_slug as _get_programs_by_type_slug
+
+
+def get_programs_by_type(site, program_type_slug):
+    """
+    Retrieves a list of programs for the site whose type's slug matches the parameter.
+    Slug is used is used as a consistent value to check since ProgramType.name is
+    a field that gets translated.
+
+    Params:
+        site (Site): The corresponding Site object to fetch programs for.
+        program_type_slug (string): The type slug that matching programs must have.
+
+    Returns:
+        A list of programs (dicts) for the given site with the given type slug
+    """
+    return _get_programs_by_type_slug(site, program_type_slug)
diff --git a/openedx/core/djangoapps/catalog/cache.py b/openedx/core/djangoapps/catalog/cache.py
index 25fa7a2515a32b0f1fe34901927ac897c99a54c0..8f3a302870f80ba853ac561fbbab4d88cfb656df 100644
--- a/openedx/core/djangoapps/catalog/cache.py
+++ b/openedx/core/djangoapps/catalog/cache.py
@@ -22,5 +22,9 @@ CATALOG_COURSE_PROGRAMS_CACHE_KEY_TPL = 'catalog-course-programs-{course_uuid}'
 # that live in the same environment).
 PROGRAMS_BY_TYPE_CACHE_KEY_TPL = 'programs-by-type-{site_id}-{program_type}'
 
+# Site-aware cache key template used to locate an item containing
+# a list of all program UUIDs with a certain program slug
+PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL = 'programs-by-type-slug-{site_id}-{program_slug}'
+
 # Template used to create cache keys for organization to program uuids.
 PROGRAMS_BY_ORGANIZATION_CACHE_KEY_TPL = 'organization-programs-{org_key}'
diff --git a/openedx/core/djangoapps/catalog/management/commands/cache_programs.py b/openedx/core/djangoapps/catalog/management/commands/cache_programs.py
index b8c78b371f8152d54020ff06ac8821ee6d88cd30..b16796fa068cd0a24539e341a1c3444b9deb335d 100644
--- a/openedx/core/djangoapps/catalog/management/commands/cache_programs.py
+++ b/openedx/core/djangoapps/catalog/management/commands/cache_programs.py
@@ -18,6 +18,7 @@ from openedx.core.djangoapps.catalog.cache import (
     PROGRAM_CACHE_KEY_TPL,
     PROGRAMS_BY_ORGANIZATION_CACHE_KEY_TPL,
     PROGRAMS_BY_TYPE_CACHE_KEY_TPL,
+    PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL,
     SITE_PATHWAY_IDS_CACHE_KEY_TPL,
     SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
 )
@@ -64,6 +65,7 @@ class Command(BaseCommand):
         courses = {}
         catalog_courses = {}
         programs_by_type = {}
+        programs_by_type_slug = {}
         organizations = {}
         for site in Site.objects.all():
             site_config = getattr(site, 'configuration', None)
@@ -93,6 +95,7 @@ class Command(BaseCommand):
             courses.update(self.get_courses(new_programs))
             catalog_courses.update(self.get_catalog_courses(new_programs))
             programs_by_type.update(self.get_programs_by_type(site, new_programs))
+            programs_by_type_slug.update(self.get_programs_by_type_slug(site, new_programs))
             organizations.update(self.get_programs_by_organization(new_programs))
 
             logger.info(u'Caching UUIDs for {total} programs for site {site_name}.'.format(
@@ -123,6 +126,9 @@ class Command(BaseCommand):
         logger.info(text_type('Caching program UUIDs by {} program types.'.format(len(programs_by_type))))
         cache.set_many(programs_by_type, None)
 
+        logger.info(text_type('Caching program UUIDs by {} program type slugs.'.format(len(programs_by_type_slug))))
+        cache.set_many(programs_by_type_slug, None)
+
         logger.info(u'Caching programs uuids for {} organizations'.format(len(organizations)))
         cache.set_many(organizations, None)
 
@@ -263,6 +269,18 @@ class Command(BaseCommand):
             programs_by_type[cache_key].append(program['uuid'])
         return programs_by_type
 
+    def get_programs_by_type_slug(self, site, programs):
+        """
+        Returns a dictionary mapping site-aware cache keys corresponding to program types
+        to lists of program uuids with that type.
+        """
+        programs_by_type_slug = defaultdict(list)
+        for program in programs.values():
+            program_slug = program.get('type_attrs', {}).get('slug')
+            cache_key = PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL.format(site_id=site.id, program_slug=program_slug)
+            programs_by_type_slug[cache_key].append(program['uuid'])
+        return programs_by_type_slug
+
     def get_programs_by_organization(self, programs):
         """
         Returns a dictionary mapping organization keys to lists of program uuids authored by that org
diff --git a/openedx/core/djangoapps/catalog/management/commands/tests/test_cache_programs.py b/openedx/core/djangoapps/catalog/management/commands/tests/test_cache_programs.py
index e1c6bd9216a1e0c58cd9400542f1d18d2df18326..e7ceef8e533ffbc8ca774bdfe0b3e126aae0cde5 100644
--- a/openedx/core/djangoapps/catalog/management/commands/tests/test_cache_programs.py
+++ b/openedx/core/djangoapps/catalog/management/commands/tests/test_cache_programs.py
@@ -14,6 +14,7 @@ from openedx.core.djangoapps.catalog.cache import (
     PATHWAY_CACHE_KEY_TPL,
     PROGRAM_CACHE_KEY_TPL,
     PROGRAMS_BY_TYPE_CACHE_KEY_TPL,
+    PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL,
     SITE_PATHWAY_IDS_CACHE_KEY_TPL,
     SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
 )
@@ -199,10 +200,15 @@ class TestCachePrograms(CatalogIntegrationMixin, CacheIsolationTestCase, SiteMix
         # program UUIDS by program type and a cached list of UUIDs by authoring organization
         for program in self.programs:
             program_type = normalize_program_type(program.get('type', 'None'))
+            program_type_slug = program.get('type_attrs', {}).get('slug')
             program_type_cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format(
                 site_id=self.site.id, program_type=program_type
             )
+            program_type_slug_cache_key = PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL.format(
+                site_id=self.site.id, program_slug=program_type_slug
+            )
             self.assertIn(program['uuid'], cache.get(program_type_cache_key))
+            self.assertIn(program['uuid'], cache.get(program_type_slug_cache_key))
 
             for organization in program['authoring_organizations']:
                 organization_cache_key = PROGRAMS_BY_ORGANIZATION_CACHE_KEY_TPL.format(
diff --git a/openedx/core/djangoapps/catalog/tests/test_utils.py b/openedx/core/djangoapps/catalog/tests/test_utils.py
index 7886b7148c7fb6ee28b81fb223c8b0f65751e7fa..f0216de2da5615c021295511e8e387792cd806b9 100644
--- a/openedx/core/djangoapps/catalog/tests/test_utils.py
+++ b/openedx/core/djangoapps/catalog/tests/test_utils.py
@@ -24,6 +24,7 @@ from openedx.core.djangoapps.catalog.cache import (
     PATHWAY_CACHE_KEY_TPL,
     PROGRAM_CACHE_KEY_TPL,
     PROGRAMS_BY_TYPE_CACHE_KEY_TPL,
+    PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL,
     SITE_PATHWAY_IDS_CACHE_KEY_TPL,
     SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
 )
@@ -33,7 +34,8 @@ from openedx.core.djangoapps.catalog.tests.factories import (
     CourseRunFactory,
     PathwayFactory,
     ProgramFactory,
-    ProgramTypeFactory
+    ProgramTypeFactory,
+    ProgramTypeAttrsFactory
 )
 from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin
 from openedx.core.djangoapps.catalog.utils import (
@@ -50,6 +52,7 @@ from openedx.core.djangoapps.catalog.utils import (
     get_program_types,
     get_programs,
     get_programs_by_type,
+    get_programs_by_type_slug,
     get_visible_sessions_for_entitlement,
     normalize_program_type,
 )
@@ -830,7 +833,7 @@ class TestProgramCourseRunCrawling(TestCase):
 
 @skip_unless_lms
 class TestGetProgramsByType(CacheIsolationTestCase):
-    """ Test for the ``get_programs_by_type()`` function. """
+    """ Test for the ``get_programs_by_type()`` and the ``get_programs_by_type_slug()`` functions. """
     ENABLED_CACHES = ['default']
 
     @classmethod
@@ -839,11 +842,26 @@ class TestGetProgramsByType(CacheIsolationTestCase):
         super(TestGetProgramsByType, cls).setUpClass()
         cls.site = SiteFactory()
         cls.other_site = SiteFactory()
-        cls.masters_program_1 = ProgramFactory.create(type='Masters')
-        cls.masters_program_2 = ProgramFactory.create(type='Masters')
-        cls.masters_program_other_site = ProgramFactory.create(type='Masters')
-        cls.bachelors_program = ProgramFactory.create(type='Bachelors')
-        cls.no_type_program = ProgramFactory.create(type=None)
+        cls.masters_program_1 = ProgramFactory.create(
+            type='Masters',
+            type_attrs=ProgramTypeAttrsFactory.create(slug="masters")
+        )
+        cls.masters_program_2 = ProgramFactory.create(
+            type='Masters',
+            type_attrs=ProgramTypeAttrsFactory.create(slug="masters")
+        )
+        cls.masters_program_other_site = ProgramFactory.create(
+            type='Masters',
+            type_attrs=ProgramTypeAttrsFactory.create(slug="masters")
+        )
+        cls.bachelors_program = ProgramFactory.create(
+            type='Bachelors',
+            type_attrs=ProgramTypeAttrsFactory.create(slug="bachelors")
+        )
+        cls.no_type_program = ProgramFactory.create(
+            type=None,
+            type_attrs=None
+        )
 
     def setUp(self):
         """ Loads program data into the cache before each test function. """
@@ -865,41 +883,58 @@ class TestGetProgramsByType(CacheIsolationTestCase):
         cache.set_many(cached_programs, None)
 
         programs_by_type = defaultdict(list)
+        programs_by_type_slug = defaultdict(list)
         for program in all_programs:
             program_type = normalize_program_type(program.get('type'))
+            program_type_slug = (program.get('type_attrs') or {}).get('slug')
             site_id = self.site.id
 
             if program == self.masters_program_other_site:
                 site_id = self.other_site.id
 
-            cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format(site_id=site_id, program_type=program_type)
-            programs_by_type[cache_key].append(program['uuid'])
+            program_type_cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format(
+                site_id=site_id,
+                program_type=program_type
+            )
+            program_type_slug_cache_key = PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL.format(
+                site_id=site_id,
+                program_slug=program_type_slug
+            )
+            programs_by_type[program_type_cache_key].append(program['uuid'])
+            programs_by_type_slug[program_type_slug_cache_key].append(program['uuid'])
 
         cache.set_many(programs_by_type, None)
+        cache.set_many(programs_by_type_slug, None)
 
     def test_get_masters_programs(self):
         expected_programs = [self.masters_program_1, self.masters_program_2]
         six.assertCountEqual(self, expected_programs, get_programs_by_type(self.site, 'masters'))
+        six.assertCountEqual(self, expected_programs, get_programs_by_type_slug(self.site, 'masters'))
 
     def test_get_bachelors_programs(self):
         expected_programs = [self.bachelors_program]
         self.assertEqual(expected_programs, get_programs_by_type(self.site, 'bachelors'))
+        self.assertEqual(expected_programs, get_programs_by_type_slug(self.site, 'bachelors'))
 
     def test_get_no_such_type_programs(self):
         expected_programs = []
         self.assertEqual(expected_programs, get_programs_by_type(self.site, 'doctorate'))
+        self.assertEqual(expected_programs, get_programs_by_type_slug(self.site, 'doctorate'))
 
     def test_get_masters_programs_other_site(self):
         expected_programs = [self.masters_program_other_site]
         self.assertEqual(expected_programs, get_programs_by_type(self.other_site, 'masters'))
+        self.assertEqual(expected_programs, get_programs_by_type_slug(self.other_site, 'masters'))
 
     def test_get_programs_null_type(self):
         expected_programs = [self.no_type_program]
         self.assertEqual(expected_programs, get_programs_by_type(self.site, None))
+        self.assertEqual(expected_programs, get_programs_by_type_slug(self.site, None))
 
     def test_get_programs_false_type(self):
         expected_programs = []
         self.assertEqual(expected_programs, get_programs_by_type(self.site, False))
+        self.assertEqual(expected_programs, get_programs_by_type_slug(self.site, False))
 
     def test_normalize_program_type(self):
         self.assertEqual('none', normalize_program_type(None))
diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py
index e87e7442842859f603cf949a32c489ee0e8f48cf..2d4b8f8f39bb5cd428373e380b5b2be97685bb37 100644
--- a/openedx/core/djangoapps/catalog/utils.py
+++ b/openedx/core/djangoapps/catalog/utils.py
@@ -23,6 +23,7 @@ from openedx.core.djangoapps.catalog.cache import (
     PATHWAY_CACHE_KEY_TPL,
     PROGRAM_CACHE_KEY_TPL,
     PROGRAMS_BY_TYPE_CACHE_KEY_TPL,
+    PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL,
     SITE_PATHWAY_IDS_CACHE_KEY_TPL,
     SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
 )
@@ -163,6 +164,29 @@ def get_programs_by_type(site, program_type):
     return get_programs_by_uuids(uuids)
 
 
+def get_programs_by_type_slug(site, program_type_slug):
+    """
+    Keyword Arguments:
+        site (Site): The corresponding Site object to fetch programs for.
+        program_type_slug (string): The type slug that matching programs must have.
+
+    Returns:
+        A list of programs for the given site with the given type slug.
+
+    Slugs are a consistent identifier whereas type (used in `get_programs_by_type`)
+    may be translated.
+    """
+    program_type_slug_cache_key = PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL.format(
+        site_id=site.id, program_slug=program_type_slug
+    )
+    uuids = cache.get(program_type_slug_cache_key, [])
+    if not uuids:
+        logger.warning(text_type(
+            'Failed to get program UUIDs from cache for site {} and type slug {}'.format(site.id, program_type_slug)
+        ))
+    return get_programs_by_uuids(uuids)
+
+
 def get_programs_by_uuids(uuids):
     """
     Gets a list of programs for the provided uuids
diff --git a/openedx/core/djangoapps/programs/api.py b/openedx/core/djangoapps/programs/api.py
new file mode 100644
index 0000000000000000000000000000000000000000..48c680d606eb447660ac8cdcd491dca2fb86de1f
--- /dev/null
+++ b/openedx/core/djangoapps/programs/api.py
@@ -0,0 +1,30 @@
+"""
+Python APIs exposed by the Programs app to other in-process apps.
+"""
+
+from .utils import is_user_enrolled_in_program_type as _is_user_enrolled_in_program_type
+
+
+def is_user_enrolled_in_program_type(user, program_type_slug, paid_modes=False, enrollments=None, entitlements=None):
+    """
+    This method will look at the learners Enrollments and Entitlements to determine
+    if a learner is enrolled in a Program of the given type.
+
+    NOTE: This method relies on the Program Cache right now. The goal is to move away from this
+    in the future.
+
+    Arguments:
+        user (User): The user we are looking for.
+        program_type_slug (str): The slug of the Program type we are looking for.
+        paid_modes (bool): Request if the user is enrolled in a Program in a paid mode, False by default.
+        enrollments (List[Dict]): Takes a serialized list of CourseEnrollments linked to the user
+        entitlements (List[CourseEntitlement]): Take a list of CourseEntitlement objects linked to the user
+
+        NOTE: Both enrollments and entitlements will be collected if they are not passed in. They are available
+        as parameters in case they were already collected, to save duplicate queries in high traffic areas.
+
+    Returns:
+        bool: True is the user is enrolled in programs of the requested type
+    """
+
+    return _is_user_enrolled_in_program_type(user, program_type_slug, paid_modes, enrollments, entitlements)
diff --git a/openedx/core/djangoapps/programs/tests/test_utils.py b/openedx/core/djangoapps/programs/tests/test_utils.py
index c988ae35ff5fda33cdd895850d0632b075b1b41e..a9d90b727599abab6e61bca09bfe4a3fb3c17a1f 100644
--- a/openedx/core/djangoapps/programs/tests/test_utils.py
+++ b/openedx/core/djangoapps/programs/tests/test_utils.py
@@ -1587,23 +1587,23 @@ class TestProgramEnrollment(SharedModuleStoreTestCase):
 
     def test_user_not_in_program(self, mock_get_programs_by_type):
         mock_get_programs_by_type.return_value = [self.program]
-        self.assertFalse(is_user_enrolled_in_program_type(user=self.user, program_type=self.MICROBACHELORS))
+        self.assertFalse(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
 
     def test_user_enrolled_in_mb_program(self, mock_get_programs_by_type):
         CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.VERIFIED)
         mock_get_programs_by_type.return_value = [self.program]
-        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type=self.MICROBACHELORS))
+        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
 
     def test_user_enrolled_unpaid_in_program(self, mock_get_programs_by_type):
         CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.AUDIT)
         mock_get_programs_by_type.return_value = [self.program]
-        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type=self.MICROBACHELORS))
+        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
 
     def test_user_enrolled_unpaid_in_program_paid_only_request(self, mock_get_programs_by_type):
         CourseEnrollmentFactory.create(user=self.user, course_id=self.course_run.id, mode=CourseMode.AUDIT)
         mock_get_programs_by_type.return_value = [self.program]
         self.assertFalse(
-            is_user_enrolled_in_program_type(user=self.user, program_type=self.MICROBACHELORS, paid_modes=True)
+            is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS, paid_modes=True)
         )
 
     def test_user_with_entitlement_no_enrollment(self, mock_get_programs_by_type):
@@ -1613,4 +1613,4 @@ class TestProgramEnrollment(SharedModuleStoreTestCase):
             course_uuid=self.program['courses'][0]['uuid']
         )
         mock_get_programs_by_type.return_value = [self.program]
-        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type=self.MICROBACHELORS))
+        self.assertTrue(is_user_enrolled_in_program_type(user=self.user, program_type_slug=self.MICROBACHELORS))
diff --git a/openedx/core/djangoapps/programs/utils.py b/openedx/core/djangoapps/programs/utils.py
index 0ccdaafb32bb90f1deb638a33dd4c06286eec0fb..99dfe55a38e5e5892f271aba8762b52037cef7e4 100644
--- a/openedx/core/djangoapps/programs/utils.py
+++ b/openedx/core/djangoapps/programs/utils.py
@@ -22,16 +22,17 @@ from pytz import utc
 from requests.exceptions import ConnectionError, Timeout
 from six.moves.urllib.parse import urljoin, urlparse, urlunparse  # pylint: disable=import-error
 
+from course_modes.api import get_paid_modes_for_course
 from course_modes.models import CourseMode
 from entitlements.api import get_active_entitlement_list_for_user
 from entitlements.models import CourseEntitlement
 from lms.djangoapps.certificates import api as certificate_api
 from lms.djangoapps.certificates.models import GeneratedCertificate
 from lms.djangoapps.commerce.utils import EcommerceService
+from openedx.core.djangoapps.catalog.api import get_programs_by_type
 from openedx.core.djangoapps.catalog.utils import (
     get_fulfillable_course_runs_for_entitlement,
     get_programs,
-    get_programs_by_type
 )
 from openedx.core.djangoapps.certificates.api import available_date_for_certificate
 from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
@@ -901,9 +902,9 @@ class ProgramMarketingDataExtender(ProgramDataExtender):
                     self.instructors.append(instructor)
 
 
-def is_user_enrolled_in_program_type(user, program_type, paid_modes=False, enrollments=None, entitlements=None):
+def is_user_enrolled_in_program_type(user, program_type_slug, paid_modes=False, enrollments=None, entitlements=None):
     """
-    This method will Look at the learners Enrollments and Entitlements to determine
+    This method will look at the learners Enrollments and Entitlements to determine
     if a learner is enrolled in a Program of the given type.
 
     NOTE: This method relies on the Program Cache right now. The goal is to move away from this
@@ -911,15 +912,20 @@ def is_user_enrolled_in_program_type(user, program_type, paid_modes=False, enrol
 
     Arguments:
         user (User): The user we are looking for.
-        program_type (String): The Program type we are looking for.
+        program_type_slug (str): The slug of the Program type we are looking for.
         paid_modes (bool): Request if the user is enrolled in a Program in a paid mode, False by default.
+        enrollments (List[Dict]): Takes a serialized list of CourseEnrollments linked to the user
+        entitlements (List[CourseEntitlement]): Take a list of CourseEntitlement objects linked to the user
+
+        NOTE: Both enrollments and entitlements will be collected if they are not passed in. They are available
+        as parameters in case they were already collected, to save duplicate queries in high traffic areas.
 
     Returns:
-        bool: True is the user is enrolled in programs of the requested Type
+        bool: True is the user is enrolled in programs of the requested type
     """
     course_runs = set()
     course_uuids = set()
-    programs = get_programs_by_type(Site.objects.get_current(), program_type)
+    programs = get_programs_by_type(Site.objects.get_current(), program_type_slug)
     if not programs:
         return False
 
@@ -941,7 +947,7 @@ def is_user_enrolled_in_program_type(user, program_type, paid_modes=False, enrol
         course_run_id = enrollment['course_details']['course_id']
         if paid_modes:
             course_run_key = CourseKey.from_string(course_run_id)
-            paid_modes = [mode.slug for mode in CourseMode.paid_modes_for_course(course_run_key)]
+            paid_modes = [mode.slug for mode in get_paid_modes_for_course(course_run_key)]
             if enrollment['mode'] in paid_modes and course_run_id in course_runs:
                 return True
         elif course_run_id in course_runs: