diff --git a/contracts/admin.py b/contracts/admin.py
index b2c97254357c9d9aeeed5ec89fc1cc47a728fd3d..929c458c96c0230857458539d716d478541f8da1 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -19,6 +19,7 @@ from .models import (
     ContractFile,
     ContractFilingArea,
     ContractIntent,
+    ContractApproval,
     ContractIssue,
     ContractType,
     Signee,
@@ -140,6 +141,11 @@ class ContractFileInline(NestedTabularInline):
     extra = 0
 
 
+class ContractApprovalInline(NestedTabularInline):
+    model = ContractApproval
+    extra = 0
+
+
 class ContractIntentInline(NestedTabularInline):
     model = ContractIntent
     extra = 0
@@ -180,6 +186,7 @@ class ContractAdmin(
         ContractFileInline,
         ContracteeSignatureInline,
         SigneeSignatureInline,
+        ContractApprovalInline,
         ContractIntentInline,
     )
 
@@ -229,7 +236,6 @@ class ContractAdmin(
                 {
                     "fields": [
                         "tender_url",
-                        "agreement_url",
                     ]
                 },
             ),
@@ -284,12 +290,13 @@ class ContractAdmin(
             FieldsetInlineOrder.INLINE,
             FieldsetInlineOrder.FIELDSET,
             FieldsetInlineOrder.INLINE,
+            FieldsetInlineOrder.INLINE,
             FieldsetInlineOrder.FIELDSET,
             FieldsetInlineOrder.FIELDSET,
         ]
 
         if context["user"].has_perm("approve", self):
-            order.insert(10, FieldsetInlineOrder.FIELDSET)
+            order.insert(11, FieldsetInlineOrder.FIELDSET)
 
         return order
 
@@ -548,6 +555,7 @@ admin.site.register(Permission)
 for model in (
     SigneeSignature,
     ContracteeSignature,
+    ContractApproval,
     ContractIntent,
 ):
     admin.site.register(model, ContractSubmodelAdmin)
diff --git a/contracts/migrations/0047_remove_contract_agreement_url_contractapproval.py b/contracts/migrations/0047_remove_contract_agreement_url_contractapproval.py
new file mode 100644
index 0000000000000000000000000000000000000000..b6a0e895f32cd94185fb5d7bf5acb0f70be9c5ff
--- /dev/null
+++ b/contracts/migrations/0047_remove_contract_agreement_url_contractapproval.py
@@ -0,0 +1,34 @@
+# Generated by Django 4.1.4 on 2023-04-16 13:13
+
+import contracts.models
+from django.db import migrations, models
+import django.db.models.deletion
+import shared.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0046_alter_contract_paper_form_state'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='contract',
+            name='agreement_url',
+        ),
+        migrations.CreateModel(
+            name='ContractApproval',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=128, verbose_name='Jméno')),
+                ('url', contracts.models.SubdomainValidatedURLField(help_text='Běžně odkaz na fórum. Využívá se např. u koaličních smluv. Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>.', max_length=256, verbose_name='Odkaz')),
+                ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='approvals', to='contracts.contract', verbose_name='Smlouva')),
+            ],
+            options={
+                'verbose_name': 'Schválení',
+                'verbose_name_plural': 'Schválení',
+            },
+            bases=(shared.models.NameStrMixin, models.Model),
+        ),
+    ]
diff --git a/contracts/migrations/0048_alter_contractapproval_options_and_more.py b/contracts/migrations/0048_alter_contractapproval_options_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef92c3e75cc60effb678845a51ba92567eada0b7
--- /dev/null
+++ b/contracts/migrations/0048_alter_contractapproval_options_and_more.py
@@ -0,0 +1,27 @@
+# Generated by Django 4.1.4 on 2023-04-16 13:17
+
+import contracts.models
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0047_remove_contract_agreement_url_contractapproval'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='contractapproval',
+            options={'verbose_name': 'Odkaz na schválení na Fóru', 'verbose_name_plural': 'Odkazy na schválení na Fóru'},
+        ),
+        migrations.AlterModelOptions(
+            name='contractintent',
+            options={'verbose_name': 'Odkaz na záměr v Piroplácení', 'verbose_name_plural': 'Odkazy na záměry v Piroplácení'},
+        ),
+        migrations.AlterField(
+            model_name='contractapproval',
+            name='url',
+            field=contracts.models.SubdomainValidatedURLField(help_text='Využívá se např. u koaličních smluv. Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>.', max_length=256, verbose_name='Odkaz'),
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index 8490179301c0336ca460e90af522e9d5e847d403..9e431ba24b0e84593654c422f2c69ca54cee042c 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -589,17 +589,6 @@ class Contract(NameStrMixin, models.Model):
         ),
     )
 
-    agreement_url = SubdomainValidatedURLField(
-        max_length=256,
-        blank=True,
-        null=True,
-        verbose_name="Odkaz na schválení",
-        help_text=mark_safe(
-            "Běžně odkaz na fórum. Využívá se např. u koaličních smluv. "
-            "Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>."
-        ),
-    )  # WARNING: Dependent on the type!
-
     issues = models.ManyToManyField(
         ContractIssue,
         blank=True,
@@ -998,6 +987,35 @@ def signing_parties_post_save_update_dates(sender, instance, *args, **kwargs) ->
     instance.contract.calculate_signing_parties_sign_date()
 
 
+class ContractApproval(NameStrMixin, models.Model):
+    name = models.CharField(
+        max_length=128,
+        verbose_name="Jméno",
+    )
+
+    url = SubdomainValidatedURLField(
+        max_length=256,
+        verbose_name="Odkaz",
+        help_text=mark_safe(
+            "Využívá se např. u koaličních smluv. Musí začínat <i>https</i> "
+            "a být pod doménou <i>pirati.cz</i>."
+        ),
+    )
+
+    contract = models.ForeignKey(
+        Contract,
+        on_delete=models.CASCADE,
+        related_name="approvals",
+        verbose_name="Smlouva",
+    )
+
+    class Meta:
+        app_label = "contracts"
+
+        verbose_name = "Odkaz na schválení na Fóru"
+        verbose_name_plural = "Odkazy na schválení na Fóru"
+
+
 class ContractIntent(NameStrMixin, models.Model):
     name = models.CharField(
         max_length=128,
@@ -1022,5 +1040,5 @@ class ContractIntent(NameStrMixin, models.Model):
     class Meta:
         app_label = "contracts"
 
-        verbose_name = "Záměr v Piroplácení"
-        verbose_name_plural = "Záměry v Piroplácení"
+        verbose_name = "Odkaz na záměr v Piroplácení"
+        verbose_name_plural = "Odkazy na záměry v Piroplácení"