diff --git a/SAS/TMSS/src/remakemigrations.py b/SAS/TMSS/src/remakemigrations.py
index a54c96c70a98b82362904b530e19b49285a7bad1..503432045e7905079d295a0faba956a987eaa66c 100755
--- a/SAS/TMSS/src/remakemigrations.py
+++ b/SAS/TMSS/src/remakemigrations.py
@@ -80,6 +80,7 @@ class Migration(migrations.Migration):
                    migrations.RunPython(populate_misc),
                    migrations.RunPython(populate_lofar_json_schemas),
                    migrations.RunPython(populate_cycles),
+                   migrations.RunPython(populate_resources),
                    migrations.RunPython(populate_projects),
                    migrations.RunPython(populate_test_scheduling_set) ]
 """
diff --git a/SAS/TMSS/src/tmss/tmssapp/migrations/0002_populate.py b/SAS/TMSS/src/tmss/tmssapp/migrations/0002_populate.py
index 5f71d8b3e7997447b18548b528557232bc454362..b24c0bccf0ded89c957fa2c6c53c62dea7428c71 100644
--- a/SAS/TMSS/src/tmss/tmssapp/migrations/0002_populate.py
+++ b/SAS/TMSS/src/tmss/tmssapp/migrations/0002_populate.py
@@ -21,5 +21,6 @@ class Migration(migrations.Migration):
                    migrations.RunPython(populate_misc),
                    migrations.RunPython(populate_lofar_json_schemas),
                    migrations.RunPython(populate_cycles),
+                   migrations.RunPython(populate_resources),
                    migrations.RunPython(populate_projects),
                    migrations.RunPython(populate_test_scheduling_set) ]
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
index ec60e4693dbec31d3049706b5490128b40840cff..854d5392c6fdf8915dd69f04ab20ffe3ef65f84a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
@@ -286,6 +286,21 @@ class Project(NamedCommonPK):
     project_category = ForeignKey('ProjectCategory', null=True, on_delete=PROTECT, help_text='Project category.')
     period_category = ForeignKey('PeriodCategory', null=True, on_delete=PROTECT, help_text='Period category.')
 
+    # also create default project quotas when projects are created
+    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
+        creating = self._state.adding  # True on create, False on update
+        super().save(force_insert, force_update, using, update_fields)
+        if creating:
+            # todo: review these defaults for being sensible
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="lta_storage"), value=1024^4, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="cep_storage"), value=1024^4, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="cep_processing_time"), value=60*60*24, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="lofar_observing_time"), value=60*60*24, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="lofar_observing_time_prio_a"), value=60*60*12, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="lofar_observing_time_prio_b"), value=60*60*12, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="support_time"), value=60*60*6, project=self)
+            ProjectQuota.objects.create(resource_type=ResourceType.objects.get(name="number_of_triggers"), value=42, project=self)
+
 
 class ProjectQuota(Model):
     project = ForeignKey('Project', related_name="project_quota", on_delete=PROTECT, help_text='Project to wich this quota belongs.')  # protected to avoid accidents
diff --git a/SAS/TMSS/src/tmss/tmssapp/populate.py b/SAS/TMSS/src/tmss/tmssapp/populate.py
index 05ce47208c77dcb0c51d29046abc9d300c7dcc95..c8ea9780f7d44872d2ab7d3859bfa6e8568cb4f6 100644
--- a/SAS/TMSS/src/tmss/tmssapp/populate.py
+++ b/SAS/TMSS/src/tmss/tmssapp/populate.py
@@ -209,7 +209,12 @@ def populate_projects(apps, schema_editor):
 def populate_resources(apps, schema_editor):
     ResourceType.objects.create(name="lta_storage", description="Amount of storage in the LTA (in bytes)")
     ResourceType.objects.create(name="cep_storage", description="Amount of storage on the CEP processing cluster (in bytes)")
-    ResourceType.objects.create(name="cep_processing_hours", description="Processing time on the CEP processing cluster (in seconds)")
+    ResourceType.objects.create(name="cep_processing_time", description="Processing time on the CEP processing cluster (in seconds)")
+    ResourceType.objects.create(name="lofar_observing_time", description="Observing time (in seconds)")
+    ResourceType.objects.create(name="lofar_observing_time_prio_a", description="Observing time with priority A (in seconds)")
+    ResourceType.objects.create(name="lofar_observing_time_prio_b", description="Observing time with priority B (in seconds)")
+    ResourceType.objects.create(name="support_time", description="Support time by human (in seconds)")
+    ResourceType.objects.create(name="number_of_triggers", description="Number of trigger events (as integer)")
 
 
 def populate_misc(apps, schema_editor):
diff --git a/SAS/TMSS/test/t_tmssapp_specification_REST_API.py b/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
index b55b2d4669438ae85fcca09021075d3d0c2e1dcf..d192f6486088fdf8d2860a7d90731150715b3b05 100755
--- a/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
+++ b/SAS/TMSS/test/t_tmssapp_specification_REST_API.py
@@ -720,9 +720,11 @@ class ProjectTestCase(unittest.TestCase):
         project_test_data = test_data_creator.Project()
 
         # POST and GET a new item and assert correctness
-        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
+        expected = project_test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, expected)
         url = r_dict['url']
-        GET_OK_and_assert_equal_expected_response(self, url, project_test_data)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
     def test_project_PUT_invalid_raises_error(self):
         PUT_and_assert_expected_response(self, BASE_URL + '/project/9876789876/', test_data_creator.Project(), 404, {})
@@ -731,40 +733,52 @@ class ProjectTestCase(unittest.TestCase):
         project_test_data = test_data_creator.Project()
 
         # POST new item, verify
-        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
+        expected = project_test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, expected)
         url = r_dict['url']
-        GET_OK_and_assert_equal_expected_response(self, url, project_test_data)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
         # PUT new values, verify
         test_data = dict(test_data_creator.Project("other description"))
         test_data['name'] = project_test_data['name']  # since name is PK, need to keep that unchanged
-        PUT_and_assert_expected_response(self, url, test_data, 200, test_data)
-        GET_OK_and_assert_equal_expected_response(self, url, test_data)
+        expected = test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        PUT_and_assert_expected_response(self, url, test_data, 200, expected)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
     def test_project_PATCH(self):
         project_test_data = test_data_creator.Project()
 
         # POST new item, verify
-        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
+        expected = project_test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, expected)
         url = r_dict['url']
-        GET_OK_and_assert_equal_expected_response(self, url, project_test_data)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
         test_patch = {"priority_rank": 1.0,
                       "tags": ["SUPERIMPORTANT"]}
 
         # PATCH item and verify
         PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
-        expected_data = dict(project_test_data)
-        expected_data.update(test_patch)
-        GET_OK_and_assert_equal_expected_response(self, url, expected_data)
+        expected.update(test_patch)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
     def test_project_DELETE(self):
         project_test_data = test_data_creator.Project()
 
         # POST new item, verify
-        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
+        expected = project_test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, expected)
         url = r_dict['url']
-        GET_OK_and_assert_equal_expected_response(self, url, project_test_data)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
+
+        # DELETE related auto-generated project_quota first
+        project_quotas = r_dict['project_quota']
+        for project_quota in project_quotas:
+            DELETE_and_assert_gone(self, project_quota)
 
         # DELETE and check it's gone
         DELETE_and_assert_gone(self, url)
@@ -776,13 +790,15 @@ class ProjectTestCase(unittest.TestCase):
         cycle_url = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)['url']
         test_data = dict(test_data_creator.Project())
         test_data['cycles'] = [cycle_url]
-        url = POST_and_assert_expected_response(self, BASE_URL + '/project/', test_data, 201, test_data)['url']
+        expected = test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        url = POST_and_assert_expected_response(self, BASE_URL + '/project/', test_data, 201, expected)['url']
 
         # verify
-        GET_OK_and_assert_equal_expected_response(self, url, test_data)
+        GET_OK_and_assert_equal_expected_response(self, url, expected)
 
         # add project reference to cycle test data (we make Django add that to the cycle in serializer)
-        cycle_test_data['projects'] = [url]  # add the
+        cycle_test_data['projects'] = [url]
 
         # Try to DELETE dependency, verify that was not successful
         # Unfortunately we don't get a nice error in json, but a Django debug page on error 500...
@@ -907,7 +923,9 @@ class ProjectQuotaTestCase(unittest.TestCase):
 
         # POST new item with dependencies
         project_test_data = test_data_creator.Project()
-        project_url = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)['url']
+        expected = project_test_data.copy()
+        expected.pop('project_quota')  # exclude project_quota from comparison, because these get auto-generated
+        project_url = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, expected)['url']
 
         project_quota_test_data = dict(test_data_creator.ProjectQuota(project_url=project_url))
         project_quota_url = POST_and_assert_expected_response(self, BASE_URL + '/project_quota/', project_quota_test_data, 201, project_quota_test_data)['url']
@@ -1595,7 +1613,7 @@ class TaskRelationDraftTestCase(unittest.TestCase):
         # assert the returned list contains related items, A list of length 1 is retrieved
         GET_and_assert_in_expected_response_result_list(self, BASE_URL + '/task_draft/%s/task_relation_draft/' % task_draft_1.id, test_data_1, 1)
         # assert an existing related producer is returned
-   
+
 
 class SchedulingUnitBlueprintTestCase(unittest.TestCase):
     @classmethod
@@ -2335,7 +2353,7 @@ class TaskSchedulingRelationBlueprintTestCase(unittest.TestCase):
         # verify
         GET_OK_and_assert_equal_expected_response(self, url, tsrb_test_data)
 
-        #Get the URL of first task blueprint 
+        #Get the URL of first task blueprint
         test_data = dict(tsrb_test_data)
         task_blueprint_url=test_data['first']