diff --git a/hypha/apply/projects/models/__init__.py b/hypha/apply/projects/models/__init__.py
index dc9e75f778ac499b349d2c3cba8a054fd9f1f1da..b100248d2dbb8a661b6db9df2ac8ead0312506b0 100644
--- a/hypha/apply/projects/models/__init__.py
+++ b/hypha/apply/projects/models/__init__.py
@@ -9,6 +9,7 @@ from .project import (
     ProjectSettings,
 )
 from .report import Report, ReportConfig, ReportPrivateFiles, ReportVersion
+from .vendor import Vendor, BankInformation
 
 __all__ = [
     'Project',
@@ -25,4 +26,6 @@ __all__ = [
     'ReportVersion',
     'ReportPrivateFiles',
     'ReportConfig',
+    'Vendor',
+    'BankInformation',
 ]
diff --git a/hypha/apply/projects/models/vendor.py b/hypha/apply/projects/models/vendor.py
new file mode 100644
index 0000000000000000000000000000000000000000..45828e1d7d07701ba872cf1649bc8d62f38f3f5a
--- /dev/null
+++ b/hypha/apply/projects/models/vendor.py
@@ -0,0 +1,81 @@
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+from babel.numbers import list_currencies, get_currency_name
+
+from hypha.apply.utils.storage import PrivateStorage
+from hypha.apply.users.models import User
+
+
+def due_diligence_documents(instance, filename):
+    return f'vendor/{instance.vendor_id}/due_diligence_documents/{filename}'
+
+
+class BankInformation(models.Model):
+    CURRENCY_CHOICES = [
+        (currency, f'{get_currency_name(currency)} - {currency}')
+        for currency in list_currencies()
+    ]
+
+    account_holder_name = models.CharField(max_length=150)
+    account_routing_number = models.CharField(max_length=10)
+    account_number = models.CharField(max_length=20)
+    account_currency = models.CharField(
+        choices=CURRENCY_CHOICES,
+        max_length=10
+    )
+    need_extra_info = models.BooleanField(default=False)
+    branch_address = models.TextField(_('Address'), blank=True)
+    iba_info = models.OneToOneField(
+        'self',
+        null=True, blank=True,
+        on_delete=models.SET_NULL,
+        related_name='bank_info',
+        verbose_name='Intermediary Bank Account Information'
+    )
+    nid_type = models.CharField(
+        max_length=25,
+        verbose_name='National Identity Document Type',
+        blank=True
+    )
+    nid_number = models.CharField(
+        max_length=20,
+        blank=True
+    )
+
+    def __str__(self):
+        return self.account_holder_name
+
+
+class Vendor(User):
+
+    TYPE_CHOICES = [
+        ('organization', 'Organization'),
+        ('personal', 'Personal'),
+    ]
+
+    contractor_name = models.CharField(max_length=150, blank=True)
+    address = models.TextField(_('Address'), blank=True)
+    type = models.CharField(max_length=15, choices=TYPE_CHOICES, blank=True)
+    required_to_pay_taxes = models.BooleanField(default=False)
+    bank_info = models.OneToOneField(
+        BankInformation,
+        on_delete=models.SET_NULL,
+        null=True, blank=True,
+    )
+    other_info = models.TextField(blank=True)
+
+    def __str__(self):
+        return self.full_name
+
+
+class DueDiligenceDocument(models.Model):
+    document = models.FileField(
+        upload_to=due_diligence_documents, storage=PrivateStorage()
+    )
+    vendor = models.ForeignKey(
+        Vendor,
+        on_delete=models.CASCADE
+    )
+
+    def __str__(self):
+        return self.vendor.full_name + ' -> ' + self.document.name