diff --git a/extension/Source/api/rest.php b/extension/Source/api/rest.php
index 2631e2755abb88028304264dd4eef37a653cb14b..4aca469d8283d098fc07d45ce8cba38a835660c8 100644
--- a/extension/Source/api/rest.php
+++ b/extension/Source/api/rest.php
@@ -15,40 +15,40 @@ require_once(__DIR__ . '/../core/exceptions/UserFormException.php');
 require_once(__DIR__ . '/../core/exceptions/CodeException.php');
 require_once(__DIR__ . '/../core/exceptions/DbException.php');
 
-$restId=array();
-$restForm=array();
+$restId = array();
+$restForm = array();
 
-$status='HTTP/1.0 409 Bad Request';
+$status = 'HTTP/1.0 409 Bad Request';
 
 try {
     try {
         $form = OnString::splitPathInfoToIdForm($_SERVER['PATH_INFO'], $restId, $restForm);
 
         // get latest `ìd`
-        $id=end($restId);
+        $id = end($restId);
 
         // Fake Bodytext setup
         $bodytext = TYPO3_RECORD_ID . '=' . $id . PHP_EOL;
         $bodytext .= TYPO3_FORM . '=' . $form . PHP_EOL;
 
-        $method=$_SERVER['REQUEST_METHOD'];
-        switch($method){
+        $method = $_SERVER['REQUEST_METHOD'];
+        switch ($method) {
             case REQUEST_METHOD_GET:
                 break;
             case REQUEST_METHOD_POST:
-                if($id!=0){
+                if ($id != 0) {
                     throw new UserFormException('Method POST needs no id or id=0', ERROR_REST_INVALID_ID);
                 }
-                $_POST  = json_decode(file_get_contents('php://input'), true);
+                $_POST = json_decode(file_get_contents('php://input'), true);
                 break;
             case REQUEST_METHOD_PUT:
-                if($id==0){
+                if ($id == 0) {
                     throw new UserFormException('Method PUT needs an id>0', ERROR_REST_INVALID_ID);
                 }
                 $_POST = json_decode(file_get_contents('php://input'), true);
                 break;
             case REQUEST_METHOD_DELETE:
-                if($id==0){
+                if ($id == 0) {
                     throw new UserFormException('Method DELETE needs an id>0', ERROR_REST_INVALID_ID);
                 }
                 break;
@@ -58,7 +58,7 @@ try {
 
         $qfq = new QuickFormQuery(['bodytext' => $bodytext]);
         $answer = $qfq->rest($restId, $restForm);
-        $status='HTTP/1.0 200 OK';
+        $status = 'HTTP/1.0 200 OK';
 
     } catch (qfq\CodeException $e) {
         $answer[API_MESSAGE] = $e->formatMessage();
diff --git a/extension/Source/core/QuickFormQuery.php b/extension/Source/core/QuickFormQuery.php
index c3e2b943cbdd8183ae450725e3681841c72d16a1..d9636c2b12863ea4152a0b7a914707b1a3ce3a8b 100644
--- a/extension/Source/core/QuickFormQuery.php
+++ b/extension/Source/core/QuickFormQuery.php
@@ -344,9 +344,13 @@ class QuickFormQuery {
         $flagApiStructureReGroup = true;
 
         // Fill STORE_FORM
-        if ($formMode === FORM_UPDATE || $formMode === FORM_SAVE) {
-            $fillStoreForm = new FillStoreForm();
-            $fillStoreForm->process($formMode);
+        switch ($formMode) {
+            case FORM_UPDATE:
+            case FORM_SAVE:
+            case FORM_REST:
+                $fillStoreForm = new FillStoreForm();
+                $fillStoreForm->process($formMode);
+                break;
         }
 
         $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT . STORE_ZERO);
@@ -372,8 +376,9 @@ class QuickFormQuery {
         Session::checkSessionExpired($this->formSpec[F_SESSION_TIMEOUT_SECONDS]);
 
         if ($formName !== false) {
-            // Validate only if there is a 'real' form (not a FORM_DELETE with only a tablename).
-            $sipFound = $this->validateForm($foundInStore, $formMode);
+            // Validate (only if there is a 'real' form, not a FORM_DELETE with only a tablename).
+            // Attention: $formModeNew will be set
+            $sipFound = $this->validateForm($foundInStore, $formMode, $formModeNew);
 
         } else {
             // FORM_DELETE without a form definition: Fake the form with only a tableName.
@@ -414,10 +419,10 @@ class QuickFormQuery {
         }
 
         // Check (and release) dirtyRecord.
-        if ($formMode === FORM_DELETE || $formMode === FORM_SAVE) {
+        if ($formModeNew === FORM_DELETE || $formModeNew === FORM_SAVE) {
             $dirty = new Dirty(false, $this->dbIndexData, $this->dbIndexQfq);
 
-            $answer = $dirty->checkDirtyAndRelease($formMode, $this->formSpec[F_RECORD_LOCK_TIMEOUT_SECONDS],
+            $answer = $dirty->checkDirtyAndRelease($formModeNew, $this->formSpec[F_RECORD_LOCK_TIMEOUT_SECONDS],
                 $this->formSpec[F_DIRTY_MODE], $this->formSpec[F_TABLE_NAME], $this->formSpec[F_PRIMARY_KEY], $recordId, true);
 
             // In case of a conflict, return immediately
@@ -429,7 +434,7 @@ class QuickFormQuery {
         }
 
         // FORM_LOAD: if there is a foreign exclusive record lock - show form in F_MODE_READONLY mode.
-        if ($formMode === FORM_LOAD) {
+        if ($formModeNew === FORM_LOAD) {
             $dirty = new Dirty(false, $this->dbIndexData, $this->dbIndexQfq);
             $recordDirty = array();
             $rcLockFound = $dirty->getCheckDirty($this->formSpec[F_TABLE_NAME], $recordId, $recordDirty, $msg);
@@ -438,7 +443,7 @@ class QuickFormQuery {
             }
         }
 
-        switch ($formMode) {
+        switch ($formModeNew) {
             case FORM_DELETE:
                 $build = new Delete($this->dbIndexData);
                 break;
@@ -471,10 +476,10 @@ class QuickFormQuery {
         }
 
         $formAction = new FormAction($this->formSpec, $this->dbArray[$this->dbIndexData], $this->phpUnit);
-        switch ($formMode) {
+        switch ($formModeNew) {
             case FORM_LOAD:
                 $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
-                $data = $build->process($formMode);
+                $data = $build->process($formModeNew);
                 $tmpClass = is_numeric($this->formSpec[F_BS_COLUMNS]) ? ('col-md-' . $this->formSpec[F_BS_COLUMNS]) : $this->formSpec[F_BS_COLUMNS];
 //                $data = Support::wrapTag("<div class='" . 'col-md-' . $this->formSpec[F_BS_COLUMNS] . "'>", $data);
                 $data = Support::wrapTag('<div class="' . $tmpClass . '">', $data);
@@ -485,7 +490,7 @@ class QuickFormQuery {
             case FORM_UPDATE:
                 $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
                 // data['form-update']=....
-                $data = $build->process($formMode);
+                $data = $build->process($formModeNew);
                 $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_LOAD);
                 break;
 
@@ -500,7 +505,7 @@ class QuickFormQuery {
             case FORM_SAVE:
                 $this->logFormSubmitRequest();
 
-                $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP);
+                $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3);
 
                 // Action: Before
                 $feTypeList = FE_TYPE_BEFORE_SAVE . ',' . ($recordId == 0 ? FE_TYPE_BEFORE_INSERT : FE_TYPE_BEFORE_UPDATE);
@@ -539,6 +544,11 @@ class QuickFormQuery {
                 // Action: Sendmail
                 $formAction->elements($rc, $this->feSpecAction, FE_TYPE_SENDMAIL);
 
+                if ($formMode == FORM_REST) {
+                    $data = ['id' => $rc];
+                    $flagApiStructureReGroup=false;
+                    break;
+                }
 
                 $customForward = $this->setForwardModePage();
 
@@ -563,10 +573,7 @@ class QuickFormQuery {
                     $feSpecNative = HelperFormElement::setLanguage($feSpecNative, $parameterLanguageFieldName);
                     $this->feSpecNative = HelperFormElement::setFeContainerFormElementId($feSpecNative, $this->formSpec[F_ID], $recordId);
 
-                    // Retrieve FE Values as JSON
-                    // $data['form-update']=...
-                    // $data = $build->process($formMode, $htmlElementNameIdZero);
-                    $data = $build->process($formMode, false, $this->feSpecNative);
+                    $data = $build->process($formModeNew, false, $this->feSpecNative);
                 }
                 break;
 
@@ -581,15 +588,15 @@ class QuickFormQuery {
                 break;
 
             case FORM_REST:
+                $flagApiStructureReGroup=false;
                 $data = $this->doRestGet();
-                $flagApiStructureReGroup = false;
                 break;
 
             default:
                 throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
         }
 
-        if ($flagApiStructureReGroup && is_array($data)) {
+        if ($flagApiStructureReGroup && is_array($data) ) {
             // $data['element-update']=...
             $data = $this->groupElementUpdateEntries($data);
         }
@@ -1091,6 +1098,7 @@ class QuickFormQuery {
 
             case FORM_SAVE:
             case FORM_UPDATE:
+            case FORM_REST:
                 $feSpecNative = $this->getNativeFormElements(SQL_FORM_ELEMENT_NATIVE_TG_COUNT, [$this->formSpec[F_ID]], $this->formSpec);
                 break;
 
@@ -1419,12 +1427,14 @@ class QuickFormQuery {
      * @throws \qfq\UserFormException
      * @internal param $foundInStore
      */
-    private function validateForm($formNameFoundInStore, $formMode) {
+    private function validateForm($formNameFoundInStore, $formMode, &$formModeNew) {
+
+        $formModeNew = $formMode;
 
         // Retrieve record_id either from SIP (preferred) or via URL
         $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore);
 
-        // no record id: Fake a definition in STORE_TYPO3.
+        // No record id: Fake a definition in STORE_TYPO3.
         if ($r === false) {
             $r = 0;
             $this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3);
@@ -1465,23 +1475,32 @@ class QuickFormQuery {
             case FORM_PERMISSION_NEVER:
                 throw new UserFormException("Loading form forbidden.", ERROR_FORM_FORBIDDEN);
                 break;
-//            case FORM_PERMISSION_REST:
-//                if ($formMode != FORM_REST) {
-//                    throw new UserFormException("Try to load a REST form", ERROR_FORM_REST);
-//                }
-//                break;
             default:
                 throw new CodeException("Unknown permission mode: '" . $permitMode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE);
         }
 
         if ($formMode == FORM_REST) {
 
-            $method = strtolower($this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT));
-            if (false === Support::findInSet($method, $this->formSpec[F_REST_METHOD])) {
-                throw new UserFormException("Form '". $this->formSpec[F_NAME]. "' is not allowed with method '$method'", ERROR_FORM_REST);
+            $method = $this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT);
+            if (false === Support::findInSet(strtolower($method), $this->formSpec[F_REST_METHOD])) {
+                throw new UserFormException("Form '" . $this->formSpec[F_NAME] . "' is not allowed with method '$method'", ERROR_FORM_REST);
             }
 
             $this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? '');
+
+            switch ($method) {
+                case REQUEST_METHOD_GET:
+                    break;
+                case REQUEST_METHOD_POST:
+                case REQUEST_METHOD_PUT:
+                    $formModeNew = FORM_SAVE;
+                    break;
+                case REQUEST_METHOD_DELETE:
+                    $formModeNew = FORM_DELETE;
+                    break;
+                default:
+                    throw new CodeException('Unknown Request Method: ' . $method, ERROR_UNKNOWN_MODE);
+            }
         }
 
         // Form Definition valid?
@@ -1898,6 +1917,9 @@ EOF;
             $ii++;
         }
 
+        $this->store::setVar(SIP_FORM, end($restForm), STORE_SIP);
+        $this->store::setVar(SIP_RECORD_ID, end($restId), STORE_SIP);
+
         return $this->doForm(FORM_REST);
 
     }
diff --git a/extension/Source/core/Save.php b/extension/Source/core/Save.php
index 9df3c42d02f44e3ecc0ba40a22722df3c2dbf8cd..f0b2504bea97b763eac3213a174af547fa409dfb 100644
--- a/extension/Source/core/Save.php
+++ b/extension/Source/core/Save.php
@@ -64,7 +64,7 @@ class Save {
     }
 
     /**
-     * Starts save process. On succcess, returns forwardmode/page.
+     * Starts save process. Returns recordId.
      *
      * @return int
      * @throws CodeException
diff --git a/extension/Source/core/store/FillStoreForm.php b/extension/Source/core/store/FillStoreForm.php
index 16ca6dd8719761b202812120b76348ff5115cd93..5426cfed4056036343d230b5efb8ecac760e8327 100644
--- a/extension/Source/core/store/FillStoreForm.php
+++ b/extension/Source/core/store/FillStoreForm.php
@@ -182,11 +182,12 @@ class FillStoreForm {
         $formModeGlobal = $this->store->getVar(F_MODE_GLOBAL, STORE_SIP . STORE_EMPTY);
 
         if ($formMode == FORM_UPDATE && $formModeGlobal == '') {
+            # During 'update': fake all elements to be not 'required'.
             $formModeGlobal = F_MODE_REQUIRED_OFF;
         }
 
         // If called through 'api/...': get STORE_TYPO3 via SIP parameter.
-        if (isset($clientValues[CLIENT_TYPO3VARS])) {
+        if (isset($clientValues[CLIENT_TYPO3VARS]) && $formMode != FORM_REST) {
             $this->store->fillTypo3StoreFromSip($clientValues[CLIENT_TYPO3VARS]);
         }
 
@@ -209,10 +210,12 @@ class FillStoreForm {
             }
         }
 
-        // Check if there is a 'new record already saved' situation:
-        // yes: the names of the input fields are submitted with '<fieldname>:0' instead of '<fieldname>:<id>'
-        // no: regular situation, take real 'recordid'
-        $fakeRecordId = isset($sipValues[SIP_MAKE_URLPARAM_UNIQ]) ? 0 : $sipValues[SIP_RECORD_ID];
+        if ($formMode != FORM_REST) {
+            // Check if there is a 'new record already saved' situation:
+            // yes: the names of the input fields are submitted with '<fieldname>:0' instead of '<fieldname>:<id>'
+            // no: regular situation, take real 'recordid'
+            $fakeRecordId = isset($sipValues[SIP_MAKE_URLPARAM_UNIQ]) ? 0 : $sipValues[SIP_RECORD_ID];
+        }
 
         // Iterate over all FormElements. Sanatize values. Built an assoc array $newValues.
         foreach ($this->feSpecNative AS $formElement) {
@@ -229,7 +232,7 @@ class FillStoreForm {
             $formElement = $this->evaluate->parseArray($formElement, $skip, $debugStack);
 
             // Get related formElement. Construct the field name used in the form.
-            $clientFieldName = HelperFormElement::buildFormElementName($formElement, $fakeRecordId);
+            $clientFieldName = ($formMode == FORM_REST) ? $formElement[FE_NAME] : HelperFormElement::buildFormElementName($formElement, $fakeRecordId);
 
             // Some Defaults
             $formElement = Support::setFeDefaults($formElement, [F_MODE => $formModeGlobal]);
@@ -309,7 +312,7 @@ class FillStoreForm {
                             // Check only if there is something.
                             if ($val !== '' && $formMode != FORM_UPDATE && $formElement[FE_MODE] != FE_MODE_HIDDEN) {
                                 $val = Sanitize::sanitize($val, $formElement[FE_CHECK_TYPE], $formElement[FE_CHECK_PATTERN],
-                                    $formElement[FE_DECIMAL_FORMAT], SANITIZE_EXCEPTION, $formElement[F_FE_DATA_PATTERN_ERROR]??'');
+                                    $formElement[FE_DECIMAL_FORMAT], SANITIZE_EXCEPTION, $formElement[F_FE_DATA_PATTERN_ERROR] ?? '');
 
                                 if ($formElement[FE_ENCODE] === FE_ENCODE_SPECIALCHAR) {
 //                                    $val = htmlspecialchars($val, ENT_QUOTES);