diff --git a/config/config.xml.default b/config/config.xml.default
index 7eb313e836723950782ad7a95ddbbb649cef0940..16f1e791a98da36b9594e0811d00aeada2e4c376 100755
--- a/config/config.xml.default
+++ b/config/config.xml.default
@@ -35,6 +35,32 @@
         <organizationalUnitCode></organizationalUnitCode>
         <signatureIdOverride></signatureIdOverride> <!-- 1 for provider (fournisseur) signature, 2 for Contralia signature, leave blank to use client signature (default) -->
     </docaposteSignature>
+    <metaSignSignature>
+        <enable>false</enable>
+        <url></url>
+        <port></port>
+        <instance></instance>
+        <certPath></certPath>
+        <certPass></certPass>
+        <certType></certType>
+        <metaSign>
+            <inDelegationOf></inDelegationOf>
+            <secret>
+                <password></password>
+                <type></type>
+            </secret>
+            <signatureKeyId></signatureKeyId>
+            <signatureProfile>
+                <signaturePolicyOid></signaturePolicyOid>
+                <attachment></attachment>
+                <format></format>
+                <augmentationLevel></augmentationLevel>
+                <signatureAlgoId></signatureAlgoId>
+                <archive></archive>
+                <requireSigningTime></requireSigningTime>
+            </signatureProfile>
+        </metaSign>
+    </metaSignSignature>
     <!-- Sort by the more secure to the less secure mode -->
     <signatureModes>
         <!-- <mode>
@@ -65,6 +91,11 @@
             <subject></subject>
             <keyUsage>digitalSignature</keyUsage>
         </mode> -->
+        <!-- <mode>
+            <id>eidas_metasign</id>
+            <color>#00FF00</color>
+            <keyUsage>metaSignSignature</keyUsage>
+        </mode> -->
         <!-- <mode>
             <id>eidas</id>
             <color>#00FF00</color>
diff --git a/lang/en.json b/lang/en.json
index 4bfab44034c51d94156e5f107721cf0289c8cef5..7cfeaca1c3be7c8bc995c6a7f2778e3bba0c170e 100755
--- a/lang/en.json
+++ b/lang/en.json
@@ -666,7 +666,10 @@
         "hardDelete": "Delete files",
         "hardDeleted": "Deleted files",
         "cannotAcces": "Unable to access document",
-		"inputCardReaderUpdateCerts": "Card entry detected, please update your certificates",
-		"outputCardReaderUpdateCerts": "Card output detected, please update your certificates"
+        "metaSignSignatureDisabled": "The metaSignSignature parameter is disabled",
+		"eidas_metasign": "Metasign Stamp",
+		"eidas_metasignUser": "Metasign Stamp",
+		"inputCardReaderUpdateCerts": "Card entry detected, updating certificates...",
+		"outputCardReaderUpdateCerts": "Card output detected, updating certificates..."
     }
-}
\ No newline at end of file
+}
diff --git a/lang/fr.json b/lang/fr.json
index 3d7c3c12a990b6ca279f5c3ccf1428ddf39a5de7..29b28724f647df17acdca9f487c0bb8a01c978d0 100755
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -665,6 +665,9 @@
 		"cannotAcces": "Impossible d'accéder au document",
 		"softDeleted": "Marqué comme supprimé",
 		"hardDeleted":"Fichiers supprimés",
+		"metaSignSignatureDisabled": "Le paramètre  metaSignSignature n'est pas activé",
+		"eidas_metasign": "Cachet Metasign",
+		"eidas_metasignUser": "Cachet Metasign",
 		"inputCardReaderUpdateCerts": "Une entrée de carte détectée, actualisation des certificats...",
 		"outputCardReaderUpdateCerts": "Une sortie de carte détectée, actualisation des certificats..."
 	}
diff --git a/src/app/document/controllers/DocumentController.php b/src/app/document/controllers/DocumentController.php
index 84a4d0944fa1ec4cb78cd87df8e6c1c32e25451d..b2cd37b8459b52873588a309522f0f60cb5d77c5 100755
--- a/src/app/document/controllers/DocumentController.php
+++ b/src/app/document/controllers/DocumentController.php
@@ -460,6 +460,7 @@ class DocumentController
 
 
         $hasEidas = false;
+        $hasMetaSignSignature = false;
         $hasElectronicSignature = false;
         foreach ($body['workflow'] as $key => $workflow) {
             $processingUser = null;
@@ -521,6 +522,9 @@ class DocumentController
             if (in_array($workflow['signatureMode'], ['eidas', 'rgs_2stars_timestamped', 'inca_card_eidas'])) {
                 $hasEidas = true;
             }
+            if ($workflow['signatureMode'] == 'eidas_metasign' && $workflow['mode'] == 'sign') {
+                $hasMetaSignSignature = true;
+            }
             if ($workflow['signatureMode'] != 'stamp' && $workflow['mode'] == 'sign') {
                 $hasElectronicSignature = true;
             }
@@ -529,7 +533,8 @@ class DocumentController
 
         $libDir    = CoreConfigModel::getLibrariesDirectory();
         $loadedXml = CoreConfigModel::getConfig();
-        if ($loadedXml->docaposteSignature->enable == 'true' && $hasEidas && (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'))) {
+        if (($loadedXml->docaposteSignature->enable == 'true' || $loadedXml->metaSignSignature->enable == 'true') && 
+            ($hasEidas || $hasMetaSignSignature) && (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php'))) {
             return $response->withStatus(500)->withJson(['errors' => 'SetaPDF-Signer library is not installed', 'lang' => 'setAPdfSignerError']);
         }
 
@@ -772,6 +777,12 @@ class DocumentController
                 return $response->withStatus(500)->withJson(['errors' => $result['errors']]);
             }
         }
+        if ($loadedXml->metaSignSignature->enable == 'true' && $hasMetaSignSignature) {
+            $metaSignInit = MetaSignSignatureController::init();
+            if (!empty($metaSignInit['errors'])) {
+                return $response->withStatus($metaSignInit['code'])->withJson(['errors' => $metaSignInit['errors']]);
+            }
+        }
 
         if (empty($body['workflow'][0]['userId'])) {
             if ($body['workflow'][0]['externalInformations']['type'] == 'yousign') {
@@ -816,16 +827,20 @@ class DocumentController
             }
             require_once($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php');
 
-            if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['signature_mode'] != 'eidas') {
+            if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && !in_array($workflow['signature_mode'], ['eidas', 'eidas_metasign'])) {
                 $url = UrlController::getCoreUrl();
                 if (strpos($url, 'https://') !== 0) {
                     return $response->withStatus(400)->withJson(['errors' => 'Url is not secured (https needed)', 'lang' => 'securedUrlNeeded']);
                 }
             }
         }
+
         if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas']) && $loadedXml->docaposteSignature->enable != 'true') {
             return $response->withStatus(400)->withJson(['errors' => 'docaposteSignature is disabled', 'lang' => 'docaposteSignatureDisabled']);
         }
+        if ($workflow['signature_mode'] == 'eidas_metasign' && $loadedXml->metaSignSignature->enable != 'true') {
+            return $response->withStatus(400)->withJson(['errors' => 'metaSignSignature is disabled', 'lang' => 'metaSignSignatureDisabled']);
+        }
 
         $body = $request->getParsedBody();
         if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['signature_mode'] == 'stamp') {
@@ -1044,7 +1059,7 @@ class DocumentController
             }
         }
 
-        if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) {
+        if (in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas', 'eidas_metasign'])) {
             if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && $workflow['mode'] == 'sign') {
                 $imageSignature = false;
                 $adr = AdrModel::getDocumentsAdr([
@@ -1054,6 +1069,10 @@ class DocumentController
                 ]);
                 $docserver          = DocserverModel::getByType(['type' => 'ESIGN', 'select' => ['path']]);
                 $pathToDocument     = $docserver['path'] . $adr[0]['path'] . $adr[0]['filename'];
+
+                if ($loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') {
+                    $pathToDocument = MetaSignSignatureController::getDocumentPath(['documentId' => (int) $args['id']]);
+                }
                 $tmpPath            = CoreConfigModel::getTmpPath();
                 $signedDocumentPath = $tmpPath . $GLOBALS['id'] . '_' . rand() . '_signedDocument.pdf';
                 $writer             = new \SetaPDF_Core_Writer_File($signedDocumentPath);
@@ -1092,39 +1111,63 @@ class DocumentController
                                     $signPosX  = ($signature['positionX'] * $format['width']) / 100;
                                     $signPosY  = ($signature['positionY'] * $format['height']) / 100;
                                 }
-                                $return = DigitalSignatureController::signHashes([
-                                    'signatureId'   => $workflow['digital_signature_id'],
-                                    'documentId'    => $args['id'],
-                                    'signatureInfo' => [
-                                        'page'          => $signature['page'],
-                                        'positionX'     => $signPosX,
-                                        'positionY'     => $signPosY,
-                                        'filePath'      => $imageTmpPath,
-                                        'signWidth'     => $signWidth
-                                    ],
-                                    'isLastSignature' => !isset($body['signatures'][$key + 1]),
-                                    'workflowId'      => $workflow['id']
-                                ]);
+                                if ($loadedXml->docaposteSignature->enable == 'true' && !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) {
+                                    $return = DigitalSignatureController::signHashes([
+                                        'signatureId'   => $workflow['digital_signature_id'],
+                                        'documentId'    => $args['id'],
+                                        'signatureInfo' => [
+                                            'page'          => $signature['page'],
+                                            'positionX'     => $signPosX,
+                                            'positionY'     => $signPosY,
+                                            'filePath'      => $imageTmpPath,
+                                            'signWidth'     => $signWidth
+                                        ],
+                                        'isLastSignature'   => !isset($body['signatures'][$key + 1]),
+                                        'workflowId'        => $workflow['id']
+                                    ]);
+                                } else if ($loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') {
+                                    $return = MetaSignSignatureController::signDocument([
+                                        'documentId'    => (int) $args['id'],
+                                        'signatureInfo' => [
+                                            'page'          => $signature['page'],
+                                            'positionX'     => $signPosX,
+                                            'positionY'     => $signPosY,
+                                            'filePath'      => $imageTmpPath,
+                                            'signWidth'     => $signWidth
+                                        ],
+                                        'isLastSignature' => !isset($body['signatures'][$key + 1])
+                                    ]);
+                                }
                                 if (!empty($return['errors'])) {
-                                    return $response->withStatus(400)->withJson($return);
+                                    return $response->withStatus($return['code'] ?? 400)->withJson(['errors' => $return['errors']]);
                                 }
                                 $imageSignature = true;
                             }
                         }
                     }
                 }
-                if (!$imageSignature) {
+                if (!$imageSignature && $loadedXml->docaposteSignature->enable == 'true' && !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) {
                     $return = DigitalSignatureController::signHashes([
-                        'signatureId'     => $workflow['digital_signature_id'],
-                        'documentId'      => $args['id'],
-                        'isLastSignature' => true,
-                        'workflowId'      => $workflow['id']
+                        'signatureId'       => $workflow['digital_signature_id'],
+                        'documentId'        => $args['id'],
+                        'workflowId'        => $workflow['id'],
+                        'isLastSignature'   => true
                     ]);
                     if (!empty($return['errors'])) {
                         return $response->withStatus(400)->withJson($return);
                     }
                 }
-            } elseif (DocumentController::ACTIONS[$args['actionId']] == 'REF' && $workflow['mode'] == 'sign') {
+                if (!$imageSignature && $loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') {
+                    $return = MetaSignSignatureController::signDocument(['documentId' => (int) $args['id'], 'isLastSignature' => true]);
+                    if (!empty($return['errors'])) {
+                        return $response->withStatus($return['code'])->withJson(['errors' => $return['errors']]);
+                    }
+                }
+            } elseif (DocumentController::ACTIONS[$args['actionId']] == 'REF' && 
+                $workflow['mode'] == 'sign' && 
+                $loadedXml->docaposteSignature->enable == 'true' && 
+                !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) {
+
                 $return = DigitalSignatureController::abort(['signatureId' => $workflow['digital_signature_id'], 'documentId' => $args['id']]);
                 if (!empty($return['errors'])) {
                     return $response->withStatus(400)->withJson($return);
diff --git a/src/app/document/controllers/MetaSignSignatureController.php b/src/app/document/controllers/MetaSignSignatureController.php
new file mode 100644
index 0000000000000000000000000000000000000000..67fa497546af7d15ad2bbf2b98da7118adcd6908
--- /dev/null
+++ b/src/app/document/controllers/MetaSignSignatureController.php
@@ -0,0 +1,318 @@
+<?php
+
+/**
+* Copyright Maarch since 2022 under license.
+* See LICENSE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+* @brief MetaSign Signature Controller
+* @author dev@maarch.org
+*/
+
+namespace Document\controllers;
+
+use Docserver\controllers\DocserverController;
+use Docserver\models\AdrModel;
+use Docserver\models\DocserverModel;
+use Document\models\DocumentModel;
+use SrcCore\models\CoreConfigModel;
+use SrcCore\models\CurlModel;
+use User\models\UserModel;
+use Workflow\models\WorkflowModel;
+use SrcCore\models\ValidatorModel;
+
+class MetaSignSignatureController 
+{
+    public static $signatureLength = 30000;
+
+
+    /**
+     * @description Get config for Metasign signature
+     * @return      false|array
+     */
+    private static function getConfig()
+    {
+        $loadedXml = CoreConfigModel::getConfig();
+        if ($loadedXml->metaSignSignature->enable == 'true') {
+            $config = [
+                'url'       => (string)$loadedXml->metaSignSignature->url,
+                'port'      => (string)$loadedXml->metaSignSignature->port,
+                'instance'  => (string)$loadedXml->metaSignSignature->instance,
+                'certPath'  => (string)$loadedXml->metaSignSignature->certPath,
+                'certPass'  => (string)$loadedXml->metaSignSignature->certPass,
+                'certType'  => (string)$loadedXml->metaSignSignature->certType,
+                'metaSign'  => [
+                    'inDelegationOf' => (string)$loadedXml->metaSignSignature->metaSign->inDelegationOf,
+                    'secret' => [
+                        "password"   => (string)$loadedXml->metaSignSignature->metaSign->secret->password,
+                        "type"       => (string)$loadedXml->metaSignSignature->metaSign->secret->type
+                    ],
+                    'signatureKeyId'    => (string)$loadedXml->metaSignSignature->metaSign->signatureKeyId,
+                    'signatureProfile'  => [
+                        'profile' => [
+                            'signaturePolicyOid' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->signaturePolicyOid,
+                            'attachment'         => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->attachment,
+                            'format'             => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->format,
+                            'augmentationLevel'  => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->augmentationLevel,
+                            'signatureAlgoId'    => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->signatureAlgoId,
+                            'archive'            => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->archive,
+                            'requireSigningTime' => (string)$loadedXml->metaSignSignature->metaSign->signatureProfile->requireSigningTime,
+                        ]
+                    ]
+                ]
+            ];
+            return $config;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @description Check if the user/certificate can sign documents
+     * @return      array|true  errors|true
+     */
+    public static function init() 
+    {
+        $config = MetaSignSignatureController::getConfig();
+        if(empty($config)) {
+            return ['code' => 400, 'errors' => "MetaSgin configuration not found!"];
+        }
+
+        $curlResponse = CurlModel::exec([
+            'url'       => $config['url'] . (empty($config['port']) ? '' : ":{$config['port']}") . "/servlets/{$config['instance']}/com.bull.security.signserver.rest/signserver/info",
+            'method'    => 'GET',
+            'headers'   => ['content-type:application/json', 'Accept: application/json'],
+            'options'   => [
+                CURLOPT_SSLCERT         => $config['certPath'],
+                CURLOPT_SSLCERTPASSWD   => $config['certPass'],
+                CURLOPT_SSLCERTTYPE     => $config['certType']
+            ]
+        ]);
+
+        if ($curlResponse['code'] != 200) {
+            return ['code' => $curlResponse['code'], 'errors' => $curlResponse['errors']];
+        } elseif (empty($curlResponse['response']['methods'])) {
+            return ['code' => 500, 'errors' => "MetaSign api endpoints not found"];
+        }elseif (!empty($curlResponse['response']['methods']) && !in_array("sigOps/signDoc", $curlResponse['response']['methods'])) {
+            return ['code' => 405, 'errors' => "User does not have access to API endpoint to 'sign document' on MetaSign"];
+        }
+        return true;
+    }
+
+    /**
+     * @description Get document path from docserver
+     * @param   array           $args
+     * @return  string|array    filePath|errors
+     */
+    public static function getDocumentPath(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['documentId']);
+        ValidatorModel::intType($args, ['documentId']);
+
+        $adr = AdrModel::getDocumentsAdr([
+            'select' => ['type', 'CONCAT(path, filename) as path_and_filename'],
+            'where'  => ['main_document_id = ?', "type IN ('DOC', 'ESIGN')"],
+            'data'   => [$args['documentId']]
+        ]);
+        if (empty($adr)) {
+            return ['code' => 404, 'errors' => '[MetaSignSignatureController][getDocumentPath] Document does not exist'];
+        }
+
+        $docAdr = [];
+        $docTypes = array_column($adr, 'path_and_filename', 'type');
+
+        if (!empty($docTypes['DOC'])) {
+            $docAdr = ['type' => 'DOC', 'pathAndFilename' => $docTypes['DOC']];
+        }
+        if (!empty($docTypes['ESIGN'])) {
+            $docAdr = ['type' => 'ESIGN', 'pathAndFilename' => $docTypes['ESIGN']];
+        }
+
+        $docserver = DocserverModel::getByType(['type' => $docAdr['type'], 'select' => ['path']]);
+        if (empty($docserver['path']) || !file_exists($docserver['path'])) {
+            return ['code' => 404, 'errors' => 'Docserver does not exist'];
+        }
+
+        $pathToDocument = $docserver['path'] . $docAdr['pathAndFilename'];
+        if (!is_file($pathToDocument) || !is_readable($pathToDocument)) {
+            return ['code' => 404, 'errors' => 'Document not found on docserver or not readable'];
+        }
+
+        return $pathToDocument;
+    }
+
+    /**
+     * @description Prepare, sign and save document
+     * @param   array       $args
+     * @return  true|array
+     */
+    public static function signDocument(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['documentId']);
+        ValidatorModel::intType($args, ['documentId']);
+        ValidatorModel::arrayType($args, ['signatureInfo']);
+
+        $config = MetaSignSignatureController::getConfig();
+        if(empty($config)) {
+            return ['code' => 400, 'errors' => "MetaSign configuration not found!"];
+        }
+
+        $pathToDocument = MetaSignSignatureController::getDocumentPath(['documentId' => $args['documentId']]);
+        if (!empty($pathToDocument['errors'])) {
+            return $pathToDocument;
+        }
+
+        $libDir = CoreConfigModel::getLibrariesDirectory();
+        if (empty($libDir) || !is_file($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php')) {
+            return ['code' => 404, 'errors' => 'SetaPDF-Signer library is not installed'];
+        }
+        require_once($libDir . 'SetaPDF-Signer/library/SetaPDF/Autoload.php');
+
+        $tmpPath            = CoreConfigModel::getTmpPath();
+        $signedDocumentPath = $tmpPath . $GLOBALS['id'] . '_' . rand() . '_signedDocument.pdf';
+        $writer             = new \SetaPDF_Core_Writer_File($signedDocumentPath);
+        $document           = \SetaPDF_Core_Document::loadByFilename($pathToDocument, $writer);
+
+        $signer = new \SetaPDF_Signer($document);
+
+        $user = UserModel::getById(['id' => $GLOBALS['id'], 'select' => ['firstname', 'lastname', 'email']]);
+        $signer->setName($user['firstname'] . ' ' . $user['lastname'] . ' ('. $user['email'] . ')');
+        $signer->setReason('Signature du document par ' . $user['firstname'] . ' ' . $user['lastname']);
+        $signer->setLocation('Maarch Parapheur');
+
+        $signer->setSignatureContentLength(self::$signatureLength);
+        $signer->setAllowSignatureContentLengthChange(true);
+
+        if (!empty($args['signatureInfo'])) {
+            $image = \SetaPDF_Core_Image::getByPath($args['signatureInfo']['filePath']);
+            $imageXObject = $image->toXObject($document);
+            $width = $args['signatureInfo']['signWidth'];
+            $height = $imageXObject->getHeight($width);
+            $signatureFieldWith = $width > 200 ? $width : 200;
+
+            $fieldName = $signer->addSignatureField(
+                'Signature_' . rand(),
+                $args['signatureInfo']['page'],
+                \SetaPDF_Signer_SignatureField::POSITION_LEFT_TOP,
+                ['x' => $args['signatureInfo']['positionX'], 'y' => -$args['signatureInfo']['positionY']],
+                $signatureFieldWith,
+                $height + 50
+            )->getQualifiedName();
+
+            $signer->setSignatureFieldName($fieldName);
+
+            $xObject = \SetaPDF_Core_XObject_Form::create($document, [0, 0, $signatureFieldWith, $height + 50]);
+            $canvas = $xObject->getCanvas();
+            $imageXObject->draw($canvas, 0, 50, $width, $height);
+
+            $font = new \SetaPDF_Core_Font_Type0_Subset(
+                $document,
+                __DIR__ . '/fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf'
+            );
+
+            $loadedXml = CoreConfigModel::getConfig();
+            if ($loadedXml->textWithDigitalSignature == 'true') {
+                $textBlock = new \SetaPDF_Core_Text_Block($font, 7);
+                $textBlock->setWidth($signatureFieldWith);
+                $textBlock->setLineHeight(14);
+                $textBlock->setPadding(2);
+                $textBlock->setText("Signé électroniquement par : " . $user['firstname'] . ' ' . $user['lastname'] . "\nLe " . date('c'));
+                $textBlock->draw($canvas, 0, 30);
+            }
+
+            $appearance = new \SetaPDF_Signer_Signature_Appearance_XObject($xObject);
+            $signer->setAppearance($appearance);
+        } else {
+            $fieldName = $signer->addSignatureField()->getQualifiedName();
+            $signer->setSignatureFieldName($fieldName);
+        }
+
+        $tmpDocument = $signer->preSign(new \SetaPDF_Core_Writer_TempFile());
+        
+        $fileHash = hash_file('sha256', $tmpDocument->getHashFile()->getPath());
+        $binaryHash = hex2bin($fileHash);
+        $resultSignature = MetaSignSignatureController::signHash([
+            'config'    => $config,
+            'docHash'   =>  base64_encode($binaryHash)]);
+        if (!empty($resultSignature['errors']) || !empty($resultSignature['code'])) {
+            return ['code' => $resultSignature['code'], 'errors' => $resultSignature['errors']];
+        }
+
+        try {
+            $signer->saveSignature($tmpDocument, $resultSignature['signatureContent']);
+        } catch (\SetaPDF_Signer_Exception_ContentLength $e) {
+            self::$signatureLength = self::$signatureLength + 1000;
+            MetaSignSignatureController::signDocument($args);
+            return true;
+        }
+
+        $storeResInfos = DocserverController::storeResourceOnDocServer([
+            'encodedFile'   => base64_encode(file_get_contents($signedDocumentPath)),
+            'format'        => 'pdf',
+            'docserverType' => 'ESIGN'
+        ]);
+
+        if (!empty($storeResInfos['errors'])) {
+            return ['errors' => $storeResInfos['errors']];
+        }
+
+        AdrModel::deleteDocumentAdr([
+            'where' => ['main_document_id = ?', 'type = ?'],
+            'data'  => [$args['documentId'], 'ESIGN']
+        ]);
+        AdrModel::createDocumentAdr([
+            'documentId'  => $args['documentId'],
+            'type'        => 'ESIGN',
+            'path'        => $storeResInfos['path'],
+            'filename'    => $storeResInfos['filename'],
+            'fingerprint' => $storeResInfos['fingerprint']
+        ]);
+        unlink($signedDocumentPath);
+
+        return true;
+    }
+
+    /**
+     * @description Send document hash to be signed from MetaSign server
+     * @param   array   $args
+     * @return  array   Return signature content from MetaSign server
+     */
+    private static function signHash(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['docHash', 'config']);
+        ValidatorModel::stringType($args, ['docHash']);
+        ValidatorModel::arrayType($args, ['config']);
+
+        $curlResponse = CurlModel::exec([
+            'url'       => $args['config']['url'] . (empty($args['config']['port']) ? '' : ":{$args['config']['port']}") . "/servlets/{$args['config']['instance']}/com.bull.security.signserver.rest/signserver/sigOps/signDoc",
+            'method'    => 'POST',
+            'headers'   => ['content-type:application/json', 'Accept: application/json'],
+            'options'   => [
+                CURLOPT_SSLCERT         => $args['config']['certPath'],
+                CURLOPT_SSLCERTPASSWD   => $args['config']['certPass'],
+                CURLOPT_SSLCERTTYPE     => $args['config']['certType']
+            ],
+            'body'      => json_encode([
+                "inDelegationOf" => $args['config']['metaSign']['inDelegationOf'],
+                "secret" => [
+                    "password" => $args['config']['metaSign']['secret']['password'],
+                    "type"  => $args['config']['metaSign']['secret']['type']
+                ],
+                "signatureKeyId" => $args['config']['metaSign']['signatureKeyId'],
+                "signatureProfile" => $args['config']['metaSign']['signatureProfile'],
+                "document" => [
+                    "docHash"  => $args['docHash']
+                ]
+            ])
+        ]);
+
+        if ($curlResponse['code'] != 200) {
+            return ['code' => $curlResponse['code'], 'errors' => $curlResponse['response']['errorInfo'] ?? $curlResponse['errors']];
+        }
+
+        return ['signatureContent' => base64_decode($curlResponse['response']['signatureContent']['bytes'])];
+    }
+}
\ No newline at end of file
diff --git a/src/app/history/controllers/HistoryController.php b/src/app/history/controllers/HistoryController.php
index 2d0270b5472506a3745dad4f000935ab805e9804..adf0e120988ef8b057ae43fa180cd7cde72b7c57 100644
--- a/src/app/history/controllers/HistoryController.php
+++ b/src/app/history/controllers/HistoryController.php
@@ -402,7 +402,7 @@ class HistoryController
         $workflowTerminated   = true;
         $workflowCompleted    = true;
         foreach ($workflow as $step) {
-            if (!$hasCertificate && in_array($step['signature_mode'], ['eidas', 'rgs_2stars', 'rgs_2stars_timestamped', 'inca_card', 'inca_card_eidas'])) {
+            if (!$hasCertificate && in_array($step['signature_mode'], ['eidas', 'eidas_metasign', 'rgs_2stars', 'rgs_2stars_timestamped', 'inca_card', 'inca_card_eidas'])) {
                 $hasCertificate = true;
             }
             if (empty($step['status'])) {
diff --git a/src/core/models/CurlModel.php b/src/core/models/CurlModel.php
index e84922af4dd32e169ab285346cef2879fb70ef79..6392ea6c725221a5c9f8bfa2d4195cfe2c15bc8d 100755
--- a/src/core/models/CurlModel.php
+++ b/src/core/models/CurlModel.php
@@ -22,7 +22,7 @@ class CurlModel
     {
         ValidatorModel::notEmpty($args, ['url', 'method']);
         ValidatorModel::stringType($args, ['url', 'method']);
-        ValidatorModel::arrayType($args, ['headers', 'queryParams', 'basicAuth', 'bearerAuth']);
+        ValidatorModel::arrayType($args, ['headers', 'queryParams', 'basicAuth', 'bearerAuth', 'options']);
         ValidatorModel::boolType($args, ['isXml']);
 
         $args['isXml'] = $args['isXml'] ?? false;
@@ -54,6 +54,13 @@ class CurlModel
             }
         }
 
+        //Options
+        if (!empty($args['options'])) {
+            foreach ($args['options'] as $key => $option) {
+                $opts[$key] = $option;
+            }
+        }
+
         //Body
         if (!empty($args['body'])) {
             $opts[CURLOPT_POSTFIELDS] = $args['body'];