diff --git a/Civi/Api4/Generic/Traits/DAOActionTrait.php b/Civi/Api4/Generic/Traits/DAOActionTrait.php
index af611354480c2320c8082e248b86774715c7a329..76df9951a41d4b58eaaba7e34dd860be6bcaa49b 100644
--- a/Civi/Api4/Generic/Traits/DAOActionTrait.php
+++ b/Civi/Api4/Generic/Traits/DAOActionTrait.php
@@ -164,6 +164,35 @@ trait DAOActionTrait {
     return $result;
   }
 
+  /**
+   * @inheritDoc
+   */
+  protected function formatWriteValues(&$record) {
+    $this->resolveFKValues($record);
+    parent::formatWriteValues($record);
+  }
+
+  /**
+   * Looks up an id based on some other property of an fk entity
+   *
+   * @param array $record
+   */
+  private function resolveFKValues(array &$record): void {
+    foreach ($record as $key => $value) {
+      if (substr_count($key, '.') !== 1) {
+        continue;
+      }
+      [$fieldName, $fkField] = explode('.', $key);
+      $field = $this->entityFields()[$fieldName] ?? NULL;
+      if (!$field || empty($field['fk_entity'])) {
+        continue;
+      }
+      $fkDao = CoreUtil::getBAOFromApiName($field['fk_entity']);
+      $record[$fieldName] = \CRM_Core_DAO::getFieldValue($fkDao, $value, 'id', $fkField);
+      unset($record[$key]);
+    }
+  }
+
   /**
    * @param array $params
    * @param int $entityId
diff --git a/tests/phpunit/api/v4/Action/FkJoinTest.php b/tests/phpunit/api/v4/Action/FkJoinTest.php
index dcacfd0efa11c9e26bb08342a48a0e834f8fbf38..efadad04754499b6fbb57678d1d8a2f4e03d4a79 100644
--- a/tests/phpunit/api/v4/Action/FkJoinTest.php
+++ b/tests/phpunit/api/v4/Action/FkJoinTest.php
@@ -161,51 +161,52 @@ class FkJoinTest extends UnitTestCase {
   }
 
   public function testBridgeJoinTags() {
-    $tag1 = Tag::create()->setCheckPermissions(FALSE)
+    $tag1 = Tag::create(FALSE)
       ->addValue('name', uniqid('join1'))
       ->execute()
       ->first()['name'];
-    $tag2 = Tag::create()->setCheckPermissions(FALSE)
+    $tag2 = Tag::create(FALSE)
       ->addValue('name', uniqid('join2'))
       ->execute()
       ->first()['name'];
-    $tag3 = Tag::create()->setCheckPermissions(FALSE)
+    $tag3 = Tag::create(FALSE)
       ->addValue('name', uniqid('join3'))
       ->execute()
       ->first()['name'];
-
-    $cid1 = Contact::create()->setCheckPermissions(FALSE)
+    // Create using pseudoconstant syntax (:name)
+    $cid1 = Contact::create(FALSE)
       ->addValue('first_name', 'Aaa')
       ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag1]))
       ->addChain('tag2', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag2]))
       ->execute()
       ->first()['id'];
-    $cid2 = Contact::create()->setCheckPermissions(FALSE)
+    // Create using fk syntax (.name)
+    $cid2 = Contact::create(FALSE)
       ->addValue('first_name', 'Bbb')
-      ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag1]))
-      ->addChain('tag3', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id:name' => $tag3]))
+      ->addChain('tag1', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id.name' => $tag1]))
+      ->addChain('tag3', EntityTag::create()->setValues(['entity_id' => '$id', 'tag_id.name' => $tag3]))
       ->execute()
       ->first()['id'];
-    $cid3 = Contact::create()->setCheckPermissions(FALSE)
+    $cid3 = Contact::create(FALSE)
       ->addValue('first_name', 'Ccc')
       ->execute()
       ->first()['id'];
 
-    $required = Contact::get()->setCheckPermissions(FALSE)
+    $required = Contact::get(FALSE)
       ->addJoin('Tag', TRUE, 'EntityTag')
       ->addSelect('first_name', 'tag.name')
       ->addWhere('id', 'IN', [$cid1, $cid2, $cid3])
       ->execute();
     $this->assertCount(4, $required);
 
-    $optional = Contact::get()->setCheckPermissions(FALSE)
+    $optional = Contact::get(FALSE)
       ->addJoin('Tag', FALSE, 'EntityTag', ['tag.name', 'IN', [$tag1, $tag2, $tag3]])
       ->addSelect('first_name', 'tag.name')
       ->addWhere('id', 'IN', [$cid1, $cid2, $cid3])
       ->execute();
     $this->assertCount(5, $optional);
 
-    $grouped = Contact::get()->setCheckPermissions(FALSE)
+    $grouped = Contact::get(FALSE)
       ->addJoin('Tag', FALSE, 'EntityTag', ['tag.name', 'IN', [$tag1, $tag3]])
       ->addSelect('first_name', 'COUNT(tag.name) AS tag_count')
       ->addWhere('id', 'IN', [$cid1, $cid2, $cid3])
@@ -215,7 +216,7 @@ class FkJoinTest extends UnitTestCase {
     $this->assertEquals(2, (int) $grouped[$cid2]['tag_count']);
     $this->assertEquals(0, (int) $grouped[$cid3]['tag_count']);
 
-    $reverse = Tag::get()->setCheckPermissions(FALSE)
+    $reverse = Tag::get(FALSE)
       ->addJoin('Contact', FALSE, 'EntityTag', ['contact.id', 'IN', [$cid1, $cid2, $cid3]])
       ->addGroupBy('id')
       ->addSelect('name', 'COUNT(contact.id) AS contacts')
@@ -226,7 +227,7 @@ class FkJoinTest extends UnitTestCase {
   }
 
   public function testBridgeJoinRelationshipContactActivity() {
-    $cid1 = Contact::create()->setCheckPermissions(FALSE)
+    $cid1 = Contact::create(FALSE)
       ->addValue('first_name', 'Aaa')
       ->addChain('activity', Activity::create()
         ->addValue('activity_type_id:name', 'Meeting')
@@ -235,7 +236,7 @@ class FkJoinTest extends UnitTestCase {
       )
       ->execute()
       ->first()['id'];
-    $cid2 = Contact::create()->setCheckPermissions(FALSE)
+    $cid2 = Contact::create(FALSE)
       ->addValue('first_name', 'Bbb')
       ->addChain('activity', Activity::create()
         ->addValue('activity_type_id:name', 'Phone Call')
@@ -247,7 +248,7 @@ class FkJoinTest extends UnitTestCase {
       )
       ->execute()
       ->first()['id'];
-    $cid3 = Contact::create()->setCheckPermissions(FALSE)
+    $cid3 = Contact::create(FALSE)
       ->addValue('first_name', 'Ccc')
       ->addChain('activity', Activity::create()
         ->addValue('activity_type_id:name', 'Meeting')
diff --git a/tests/phpunit/api/v4/Entity/SystemTest.php b/tests/phpunit/api/v4/Entity/SystemTest.php
index 11203e70ec8ad9a7f44e416875395997e30b0429..435c7cb98f37c088ff4f9c9bc964cd9074553ec7 100644
--- a/tests/phpunit/api/v4/Entity/SystemTest.php
+++ b/tests/phpunit/api/v4/Entity/SystemTest.php
@@ -50,7 +50,7 @@ class SystemTest extends UnitTestCase {
     $this->assertCount(1, $check);
 
     // Ensure cron check has not run
-    $this->assertCount(0, StatusPreference::get()->setCheckPermissions(FALSE)->addWhere('name', '=', 'checkLastCron')->execute());
+    $this->assertCount(0, StatusPreference::get(FALSE)->addWhere('name', '=', 'checkLastCron')->execute());
 
     // Will run on non-prod site with $includeDisabled.
     // Giving a more-specific name will run all checks with less-specific names too
@@ -60,7 +60,7 @@ class SystemTest extends UnitTestCase {
     $this->assertEquals('Ok', $check['hook_civicrm_check']['title']);
 
     // We know the cron check has run because it would have left a record marked 'new'
-    $record = StatusPreference::get()->setCheckPermissions(FALSE)->addWhere('name', '=', 'checkLastCron')->execute()->first();
+    $record = StatusPreference::get(FALSE)->addWhere('name', '=', 'checkLastCron')->execute()->first();
     $this->assertEquals('new', $record['prefs']);
 
     // Restore env