diff --git a/pay-api/migrations/versions/2024_12_18_695a899f8a25_add_payment_methods_to_corp_types.py b/pay-api/migrations/versions/2024_12_18_695a899f8a25_add_payment_methods_to_corp_types.py
new file mode 100644
index 000000000..b52c007dd
--- /dev/null
+++ b/pay-api/migrations/versions/2024_12_18_695a899f8a25_add_payment_methods_to_corp_types.py
@@ -0,0 +1,50 @@
+"""add payment_methods column to corp_types table, and insert payment methods based on product
+
+Revision ID: 695a899f8a25
+Revises: 4f3a44eeade8
+Create Date: 2024-12-18 11:32:07.538729
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+# Note you may see foreign keys with distribution_codes_history
+# For disbursement_distribution_code_id, service_fee_distribution_code_id
+# Please ignore those lines and don't include in migration.
+
+revision = '695a899f8a25'
+down_revision = '4f3a44eeade8'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    op.add_column(
+        'corp_types',
+        sa.Column('payment_methods', sa.ARRAY(sa.String()), nullable=True)
+    )
+
+    op.execute("""
+        UPDATE corp_types 
+        SET payment_methods = 
+            CASE product
+                WHEN 'BUSINESS' THEN ARRAY['PAD', 'DIRECT_PAY', 'EFT', 'EJV', 'ONLINE_BANKING', 'DRAWDOWN', 'INTERNAL']
+                WHEN 'NRO' THEN ARRAY['DIRECT_PAY','PAD', 'DRAWDOWN', 'INTERNAL']
+                WHEN 'RPPR' THEN ARRAY['PAD', 'DRAWDOWN', 'INTERNAL']
+                WHEN 'VS' THEN ARRAY['DIRECT_PAY','PAD', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
+                WHEN 'RPT' THEN ARRAY['PAD', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
+                WHEN 'BUSINESS_SEARCH' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EJV', 'EFT', 'INTERNAL']
+                WHEN 'CSO' THEN ARRAY['PAD', 'DRAWDOWN', 'EJV', 'INTERNAL']
+                WHEN 'ESRA' THEN ARRAY['PAD', 'DRAWDOWN', 'EJV', 'INTERNAL']
+                WHEN 'PPR' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
+                WHEN 'MHR' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
+                ELSE ARRAY['INTERNAL']
+            END
+        WHERE product IS NOT NULL
+    """)
+
+
+def downgrade():
+    op.drop_column('corp_types', 'payment_methods')
diff --git a/pay-api/src/pay_api/models/corp_type.py b/pay-api/src/pay_api/models/corp_type.py
index eb2cfe5af..516b0af2e 100644
--- a/pay-api/src/pay_api/models/corp_type.py
+++ b/pay-api/src/pay_api/models/corp_type.py
@@ -47,6 +47,7 @@ class CorpType(db.Model, CodeTable):
             "description",
             "has_partner_disbursements",
             "is_online_banking_allowed",
+            "payment_methods",
             "product",
         ]
     }
@@ -61,6 +62,7 @@ class CorpType(db.Model, CodeTable):
     has_partner_disbursements = db.Column(Boolean(), default=False)
     batch_type = db.Column(db.String(2), nullable=True)
     product = db.Column(db.String(20), nullable=True)
+    payment_methods = db.Column(db.ARRAY(db.String()), nullable=True)
 
     def save(self):
         """Save corp type."""
diff --git a/pay-api/src/pay_api/resources/v1/code.py b/pay-api/src/pay_api/resources/v1/code.py
index 2f3be890f..052a5f892 100644
--- a/pay-api/src/pay_api/resources/v1/code.py
+++ b/pay-api/src/pay_api/resources/v1/code.py
@@ -35,3 +35,11 @@ def get_codes_by_type(code_type):
 def get_code(code_type, code):
     """Return all codes based on code_type."""
     return CodeService.find_code_value_by_type_and_code(code_type, code), HTTPStatus.OK
+
+
+@bp.route("/valid_payment_methods", methods=["GET", "OPTIONS"])
+@bp.route("/valid_payment_methods/<string:product_code>", methods=["GET", "OPTIONS"])
+@cross_origin(origins="*", methods=["GET"])
+def get_valid_payment_methods(product_code=None):
+    """Return all valid payment methods based on product code."""
+    return CodeService.find_valid_payment_methods_by_product_code(product_code), HTTPStatus.OK
diff --git a/pay-api/src/pay_api/services/code.py b/pay-api/src/pay_api/services/code.py
index ef25a5489..d6b3e1058 100644
--- a/pay-api/src/pay_api/services/code.py
+++ b/pay-api/src/pay_api/services/code.py
@@ -94,3 +94,22 @@ def find_code_value_by_type_and_code(cls, code_type: str, code: str):
                 code_response = schema.dump(codes_model, many=False)
         current_app.logger.debug(">find_code_value_by_type_and_code")
         return code_response
+
+    @classmethod
+    def find_valid_payment_methods_by_product_code(cls, product_code: str | None = None) -> dict:
+        """Find payment methods for a product."""
+        if not product_code:
+            corp_types = (
+                CorpType.query.with_entities(CorpType.product, CorpType.payment_methods)
+                .filter(CorpType.product.isnot(None))  # Exclude None at the query level
+                .distinct()
+                .all()
+            )
+            return dict(corp_types)
+
+        corp_type = (
+            CorpType.query.with_entities(CorpType.product, CorpType.payment_methods)
+            .filter_by(product=product_code)
+            .first()
+        )
+        return {corp_type.product: corp_type.payment_methods} if corp_type else {}
diff --git a/pay-api/tests/unit/api/test_code.py b/pay-api/tests/unit/api/test_code.py
index 39c0af4b4..d494a4a49 100755
--- a/pay-api/tests/unit/api/test_code.py
+++ b/pay-api/tests/unit/api/test_code.py
@@ -47,3 +47,18 @@ def test_find_codes(session, client, jwt, app, code: Code):
     """Assert that the endpoint returns 200."""
     rv = client.get(f"/api/v1/codes/{code.value}", headers={})
     assert rv.status_code == 200
+
+
+def test_get_valid_payment_methods(session, client, jwt, app):
+    """Assert that the valid payment methods endpoint works."""
+    rv = client.get("/api/v1/codes/valid_payment_methods", headers={})
+    assert rv.status_code == 200
+    assert isinstance(rv.json, dict)
+
+    rv = client.get("/api/v1/codes/valid_payment_methods/VS", headers={})
+    assert rv.status_code == 200
+    assert isinstance(rv.json, dict)
+
+    rv = client.get("/api/v1/codes/valid_payment_methods/INVALID", headers={})
+    assert rv.status_code == 200
+    assert rv.json == {}
diff --git a/pay-api/tests/unit/models/test_corp_type.py b/pay-api/tests/unit/models/test_corp_type.py
index 2b7785c80..c872751ba 100644
--- a/pay-api/tests/unit/models/test_corp_type.py
+++ b/pay-api/tests/unit/models/test_corp_type.py
@@ -20,9 +20,14 @@
 from pay_api.models import CorpType
 
 
-def factory_corp_type(corp_type_code: str, corp_description: str):
+def factory_corp_type(corp_type_code: str, corp_description: str, product: str = None, payment_methods: list = None):
     """Return a valid Corp Type object."""
-    return CorpType(code=corp_type_code, description=corp_description)
+    corp_type = CorpType(code=corp_type_code, description=corp_description)
+    if product:
+        corp_type.product = product
+    if payment_methods:
+        corp_type.payment_methods = payment_methods
+    return corp_type
 
 
 def test_corp_type(session):
@@ -54,3 +59,19 @@ def test_corp_type_by_invalid_code(session):
 
     b = CorpType.find_by_code("AB")
     assert b is None
+
+
+def test_payment_methods(session):
+    """Assert that payment methods are stored and retrieved correctly."""
+    business_corp = factory_corp_type(
+        "XX",
+        "Business",
+        product="BUSINESS",
+        payment_methods=['PAD', 'DIRECT_PAY', 'ONLINE_BANKING', 'DRAWDOWN']
+    )
+    session.add(business_corp)
+    session.commit()
+
+    retrieved_corp = CorpType.find_by_code("XX")
+    assert retrieved_corp is not None
+    assert retrieved_corp.payment_methods == ['PAD', 'DIRECT_PAY', 'ONLINE_BANKING', 'DRAWDOWN']
diff --git a/pay-api/tests/unit/services/test_code.py b/pay-api/tests/unit/services/test_code.py
index 55c493f8c..4f198cf17 100644
--- a/pay-api/tests/unit/services/test_code.py
+++ b/pay-api/tests/unit/services/test_code.py
@@ -58,3 +58,18 @@ def test_find_payment_types_code_values(session):
     codes = CodeService.find_code_values_by_type(Code.INVOICE_STATUS.value)
     assert codes is not None
     assert len(codes) > 0
+
+
+def test_find_valid_payment_methods_by_product_code(session):
+    """Assert that valid payment methods are returned for products."""
+    payment_methods = CodeService.find_valid_payment_methods_by_product_code()
+    assert payment_methods is not None
+    assert isinstance(payment_methods, dict)
+
+    business_payment_methods = CodeService.find_valid_payment_methods_by_product_code('BUSINESS')
+    assert business_payment_methods is not None
+    assert 'BUSINESS' in business_payment_methods
+    assert isinstance(business_payment_methods['BUSINESS'], list)
+
+    invalid_payment_methods = CodeService.find_valid_payment_methods_by_product_code('INVALID')
+    assert invalid_payment_methods == {}