diff --git a/common/djangoapps/entitlements/api/v1/tests/test_views.py b/common/djangoapps/entitlements/api/v1/tests/test_views.py
index a52c248a37e0dee0230bbd7f33e06f19ab16bc16..eb7a34248c991515db0faea4c611b51a147ae32a 100644
--- a/common/djangoapps/entitlements/api/v1/tests/test_views.py
+++ b/common/djangoapps/entitlements/api/v1/tests/test_views.py
@@ -20,6 +20,7 @@ from course_modes.tests.factories import CourseModeFactory
 from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
 from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
 from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
+from openedx.core.djangoapps.user_api.models import UserOrgTag
 from student.models import CourseEnrollment
 from student.tests.factories import (TEST_PASSWORD, CourseEnrollmentFactory, UserFactory)
 
@@ -309,6 +310,47 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
         )
         assert course_entitlement.policy == policy
 
+    @patch("entitlements.api.v1.views.get_owners_for_course")
+    def test_email_opt_in_single_org(self, mock_get_owners):
+        course_uuid = uuid.uuid4()
+        entitlement_data = self._get_data_set(self.user, str(course_uuid))
+        entitlement_data['email_opt_in'] = True
+
+        org = u'particularly'
+        mock_get_owners.return_value = [{'key': org}]
+
+        response = self.client.post(
+            self.entitlements_list_url,
+            data=json.dumps(entitlement_data),
+            content_type='application/json',
+        )
+        assert response.status_code == 201
+
+        result_obj = UserOrgTag.objects.get(user=self.user, org=org, key='email-optin')
+        self.assertEqual(result_obj.value, u"True")
+
+    @patch("entitlements.api.v1.views.get_owners_for_course")
+    def test_email_opt_in_multiple_orgs(self, mock_get_owners):
+        course_uuid = uuid.uuid4()
+        entitlement_data = self._get_data_set(self.user, str(course_uuid))
+        entitlement_data['email_opt_in'] = True
+
+        org_1 = u'particularly'
+        org_2 = u'underwood'
+        mock_get_owners.return_value = [{'key': org_1}, {'key': org_2}]
+
+        response = self.client.post(
+            self.entitlements_list_url,
+            data=json.dumps(entitlement_data),
+            content_type='application/json',
+        )
+        assert response.status_code == 201
+
+        result_obj = UserOrgTag.objects.get(user=self.user, org=org_1, key='email-optin')
+        self.assertEqual(result_obj.value, u"True")
+        result_obj = UserOrgTag.objects.get(user=self.user, org=org_2, key='email-optin')
+        self.assertEqual(result_obj.value, u"True")
+
     def test_add_entitlement_with_support_detail(self):
         """
         Verify that an EntitlementSupportDetail entry is made when the request includes support interaction information.
diff --git a/common/djangoapps/entitlements/api/v1/views.py b/common/djangoapps/entitlements/api/v1/views.py
index 654df32a19a6a8eec5d01aa18a83eadc6af422ee..c8bf87203fa9a4599dfb7f8a07b2f5396c765be4 100644
--- a/common/djangoapps/entitlements/api/v1/views.py
+++ b/common/djangoapps/entitlements/api/v1/views.py
@@ -19,9 +19,10 @@ from entitlements.api.v1.permissions import IsAdminOrSupportOrAuthenticatedReadO
 from entitlements.api.v1.serializers import CourseEntitlementSerializer
 from entitlements.models import CourseEntitlement, CourseEntitlementPolicy, CourseEntitlementSupportDetail
 from entitlements.utils import is_course_run_entitlement_fulfillable
-from openedx.core.djangoapps.catalog.utils import get_course_runs_for_course
+from openedx.core.djangoapps.catalog.utils import get_course_runs_for_course, get_owners_for_course
 from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticationCrossDomainCsrf
+from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in
 from student.models import AlreadyEnrolledError, CourseEnrollment, CourseEnrollmentException
 
 log = logging.getLogger(__name__)
@@ -158,6 +159,8 @@ class EntitlementViewSet(viewsets.ModelViewSet):
 
     def create(self, request, *args, **kwargs):
         support_details = request.data.pop('support_details', [])
+        email_opt_in = request.data.pop('email_opt_in', False)
+
         serializer = self.get_serializer(data=request.data)
         serializer.is_valid(raise_exception=True)
         self.perform_create(serializer)
@@ -165,6 +168,12 @@ class EntitlementViewSet(viewsets.ModelViewSet):
         entitlement = serializer.instance
         set_entitlement_policy(entitlement, request.site)
 
+        # The owners for a course are the organizations that own the course. By taking owner.key,
+        # we are able to pass in the organization key for email_opt_in
+        owners = get_owners_for_course(entitlement.course_uuid)
+        for owner in owners:
+            update_email_opt_in(entitlement.user, owner['key'], email_opt_in)
+
         if support_details:
             for support_detail in support_details:
                 support_detail['entitlement'] = entitlement
diff --git a/openedx/core/djangoapps/catalog/tests/test_utils.py b/openedx/core/djangoapps/catalog/tests/test_utils.py
index 0d447cbc13c02fc156d01a055cfdf2117fdf7ce5..a0a5bdaed189e4d8a8788f96746a234f277c6aa5 100644
--- a/openedx/core/djangoapps/catalog/tests/test_utils.py
+++ b/openedx/core/djangoapps/catalog/tests/test_utils.py
@@ -35,9 +35,10 @@ from openedx.core.djangoapps.catalog.utils import (
     get_course_runs,
     get_course_runs_for_course,
     get_course_run_details,
-    get_pathways,
     get_currency_data,
     get_localized_price_text,
+    get_owners_for_course,
+    get_pathways,
     get_program_types,
     get_programs,
     get_visible_sessions_for_entitlement
@@ -464,6 +465,31 @@ class TestGetCourseRuns(CatalogIntegrationMixin, TestCase):
         self.assertEqual(data, catalog_course_runs)
 
 
+@skip_unless_lms
+@mock.patch(UTILS_MODULE + '.get_edx_api_data')
+class TestGetCourseOwners(CatalogIntegrationMixin, TestCase):
+    """
+    Tests covering retrieval of course runs from the catalog service.
+    """
+    def setUp(self):
+        super(TestGetCourseOwners, self).setUp()
+
+        self.catalog_integration = self.create_catalog_integration(cache_ttl=1)
+        self.user = UserFactory(username=self.catalog_integration.service_username)
+
+    def test_get_course_owners_by_course(self, mock_get_edx_api_data):
+        """
+        Test retrieval of course runs.
+        """
+        catalog_course_runs = CourseRunFactory.create_batch(10)
+        catalog_course = CourseFactory(course_runs=catalog_course_runs)
+        mock_get_edx_api_data.return_value = catalog_course
+
+        data = get_owners_for_course(course_uuid=str(catalog_course['uuid']))
+        self.assertTrue(mock_get_edx_api_data.called)
+        self.assertEqual(data, catalog_course['owners'])
+
+
 @skip_unless_lms
 @mock.patch(UTILS_MODULE + '.get_edx_api_data')
 class TestSessionEntitlement(CatalogIntegrationMixin, TestCase):
diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py
index a823153f2cc33be13b39f04ec40b98885edcf419..f4530a38ca99e70734af1d6d27a54fa2b6ee4e95 100644
--- a/openedx/core/djangoapps/catalog/utils.py
+++ b/openedx/core/djangoapps/catalog/utils.py
@@ -37,6 +37,45 @@ def create_catalog_api_client(user, site=None):
     return EdxRestApiClient(url, jwt=jwt)
 
 
+def check_catalog_integration_and_get_user(error_message_field):
+    """
+    Checks that catalog integration is enabled, and if so, attempts to get and
+    return the service user.
+
+    Parameters:
+        error_message_field (str): The field that will be attempted to be
+            retrieved when calling the api client. Used for the error message.
+
+    Returns:
+        Tuple of:
+            The catalog integration service user if it exists, else None
+            The catalog integration Object
+                Note: (This is necessary for future calls of functions using this method)
+    """
+    catalog_integration = CatalogIntegration.current()
+
+    if catalog_integration.is_enabled():
+        try:
+            user = catalog_integration.get_service_user()
+        except ObjectDoesNotExist:
+            logger.error(
+                'Catalog service user with username [{username}] does not exist. '
+                '{field} will not be retrieved.'.format(
+                    username=catalog_integration.service_username,
+                    field=error_message_field,
+                )
+            )
+            return None, catalog_integration
+        return user, catalog_integration
+    else:
+        logger.error(
+            'Unable to retrieve details about {field} because Catalog Integration is not enabled'.format(
+                field=error_message_field,
+            )
+        )
+        return None, catalog_integration
+
+
 def get_programs(site, uuid=None):
     """Read programs from the cache.
 
@@ -101,13 +140,8 @@ def get_program_types(name=None):
         list of dict, representing program types.
         dict, if a specific program type is requested.
     """
-    catalog_integration = CatalogIntegration.current()
-    if catalog_integration.enabled:
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            return []
-
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Program types')
+    if user:
         api = create_catalog_api_client(user)
         cache_key = '{base}.program_types'.format(base=catalog_integration.CACHE_KEY)
 
@@ -186,13 +220,8 @@ def get_currency_data():
         list of dict, representing program types.
         dict, if a specific program type is requested.
     """
-    catalog_integration = CatalogIntegration.current()
-    if catalog_integration.enabled:
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            return []
-
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Currency data')
+    if user:
         api = create_catalog_api_client(user)
         cache_key = '{base}.currency'.format(base=catalog_integration.CACHE_KEY)
 
@@ -289,18 +318,9 @@ def get_course_runs():
     Returns:
         list of dict with each record representing a course run.
     """
-    catalog_integration = CatalogIntegration.current()
     course_runs = []
-    if catalog_integration.enabled:
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            logger.error(
-                'Catalog service user with username [%s] does not exist. Course runs will not be retrieved.',
-                catalog_integration.service_username,
-            )
-            return course_runs
-
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Course runs')
+    if user:
         api = create_catalog_api_client(user)
 
         querystring = {
@@ -314,18 +334,30 @@ def get_course_runs():
 
 
 def get_course_runs_for_course(course_uuid):
-    catalog_integration = CatalogIntegration.current()
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Course runs')
+    if user:
+        api = create_catalog_api_client(user)
+        cache_key = '{base}.course.{uuid}.course_runs'.format(
+            base=catalog_integration.CACHE_KEY,
+            uuid=course_uuid
+        )
+        data = get_edx_api_data(
+            catalog_integration,
+            'courses',
+            resource_id=course_uuid,
+            api=api,
+            cache_key=cache_key if catalog_integration.is_cache_enabled else None,
+            long_term_cache=True,
+            many=False
+        )
+        return data.get('course_runs', [])
+    else:
+        return []
 
-    if catalog_integration.is_enabled():
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            logger.error(
-                'Catalog service user with username [%s] does not exist. Course runs will not be retrieved.',
-                catalog_integration.service_username,
-            )
-            return []
 
+def get_owners_for_course(course_uuid):
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Owners')
+    if user:
         api = create_catalog_api_client(user)
         cache_key = '{base}.course.{uuid}.course_runs'.format(
             base=catalog_integration.CACHE_KEY,
@@ -340,7 +372,7 @@ def get_course_runs_for_course(course_uuid):
             long_term_cache=True,
             many=False
         )
-        return data.get('course_runs', [])
+        return data.get('owners', [])
     else:
         return []
 
@@ -356,18 +388,8 @@ def get_course_uuid_for_course(course_run_key):
     Returns:
         UUID: Course UUID and None if it was not retrieved.
     """
-    catalog_integration = CatalogIntegration.current()
-
-    if catalog_integration.is_enabled():
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            logger.error(
-                'Catalog service user with username [%s] does not exist. Course UUID will not be retrieved.',
-                catalog_integration.service_username,
-            )
-            return []
-
+    user, catalog_integration = check_catalog_integration_and_get_user(error_message_field='Course UUID')
+    if user:
         api = create_catalog_api_client(user)
 
         run_cache_key = '{base}.course_run.{course_run_key}'.format(
@@ -483,27 +505,15 @@ def get_course_run_details(course_run_key, fields):
     Returns:
         dict with language, start date, end date, and max_effort details about specified course run
     """
-    catalog_integration = CatalogIntegration.current()
     course_run_details = dict()
-    if catalog_integration.enabled:
-        try:
-            user = catalog_integration.get_service_user()
-        except ObjectDoesNotExist:
-            msg = 'Catalog service user {} does not exist. Data for course_run {} will not be retrieved'.format(
-                catalog_integration.service_username,
-                course_run_key
-            )
-            logger.error(msg)
-            return course_run_details
+    user, catalog_integration = check_catalog_integration_and_get_user(
+        error_message_field='Data for course_run {}'.format(course_run_key)
+    )
+    if user:
         api = create_catalog_api_client(user)
 
         cache_key = '{base}.course_runs'.format(base=catalog_integration.CACHE_KEY)
 
         course_run_details = get_edx_api_data(catalog_integration, 'course_runs', api, resource_id=course_run_key,
                                               cache_key=cache_key, many=False, traverse_pagination=False, fields=fields)
-    else:
-        msg = 'Unable to retrieve details about course_run {} because Catalog Integration is not enabled'.format(
-            course_run_key
-        )
-        logger.error(msg)
     return course_run_details
diff --git a/openedx/core/djangoapps/user_api/preferences/tests/test_api.py b/openedx/core/djangoapps/user_api/preferences/tests/test_api.py
index 5df93fcc8c34f51ea82a87a667084b4f6b704364..47e64e95c5a0259bf673fd9a6045e4d41f204103 100644
--- a/openedx/core/djangoapps/user_api/preferences/tests/test_api.py
+++ b/openedx/core/djangoapps/user_api/preferences/tests/test_api.py
@@ -332,9 +332,9 @@ class UpdateEmailOptInTests(ModuleStoreTestCase):
     """
     Test cases to cover API-driven email list opt-in update workflows
     """
-    USERNAME = u'frank-underwood'
+    USERNAME = u'claire-underwood'
     PASSWORD = u'ṕáśśẃőŕd'
-    EMAIL = u'frank+underwood@example.com'
+    EMAIL = u'claire+underwood@example.com'
     shard = 2
 
     @ddt.data(