diff --git a/rest/index.php b/rest/index.php
index 3f1037a32bc61bb7a4f99990b141e2a2219d750d..ecb9015e440fd15b784472920a1d51c1e0463bcb 100755
--- a/rest/index.php
+++ b/rest/index.php
@@ -223,6 +223,10 @@ $app->get('/administration/statuses/new', \Status\controllers\StatusController::
 
 //Templates
 $app->get('/templates', \Template\controllers\TemplateController::class . ':get');
+$app->post('/templates', \Template\controllers\TemplateController::class . ':create');
+$app->get('/templates/{id}', \Template\controllers\TemplateController::class . ':getById');
+$app->put('/templates/{id}', \Template\controllers\TemplateController::class . ':update');
+$app->delete('/templates/{id}', \Template\controllers\TemplateController::class . ':delete');
 $app->post('/templates/{id}/duplicate', \Template\controllers\TemplateController::class . ':duplicate');
 
 //Users
diff --git a/src/app/template/controllers/TemplateController.php b/src/app/template/controllers/TemplateController.php
index f670c79f190acb522b70ba57d1bbf1ceefc213db..91c1a9f11197603646788eec3d4d472351a3262a 100644
--- a/src/app/template/controllers/TemplateController.php
+++ b/src/app/template/controllers/TemplateController.php
@@ -17,6 +17,8 @@ namespace Template\controllers;
 use Docserver\controllers\DocserverController;
 use Docserver\models\DocserverModel;
 use Group\models\ServiceModel;
+use History\controllers\HistoryController;
+use Respect\Validation\Validator;
 use Slim\Http\Request;
 use Slim\Http\Response;
 use Template\models\TemplateAssociationModel;
@@ -31,14 +33,130 @@ class TemplateController
         }
 
         $templates = TemplateModel::get();
-        foreach ($templates as $key => $template) {
-            $linkedEntities = TemplateAssociationModel::get(['select' => ['value_field'], 'where' => ['template_id = ?'], 'data' => [$template['template_id']]]);
-            foreach ($linkedEntities as $linkedEntity) {
-                $templates[$key]['entities'][] = $linkedEntity['value_field'];
+
+        return $response->withJson(['templates' => $templates]);
+    }
+
+    public function getById(Request $request, Response $response, array $aArgs)
+    {
+        if (!ServiceModel::hasService(['id' => 'admin_templates', 'userId' => $GLOBALS['userId'], 'location' => 'templates', 'type' => 'admin'])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
+        }
+
+        $template = TemplateModel::getById(['id' => $aArgs['id']]);
+        $template['entities'] = [];
+
+        $linkedEntities = TemplateAssociationModel::get(['select' => ['value_field'], 'where' => ['template_id = ?'], 'data' => [$template['template_id']]]);
+        foreach ($linkedEntities as $linkedEntity) {
+            $template['entities'][] = $linkedEntity['value_field'];
+        }
+
+        return $response->withJson(['template' => $template]);
+    }
+
+    public function create(Request $request, Response $response)
+    {
+        if (!ServiceModel::hasService(['id' => 'admin_templates', 'userId' => $GLOBALS['userId'], 'location' => 'templates', 'type' => 'admin'])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
+        }
+
+        $data = $request->getParams();
+
+        $check = Validator::stringType()->notEmpty()->validate($data['template_label']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_comment']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_content']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_type']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_datasource']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_target']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_attachment_type']);
+        if (!$check) {
+            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
+        }
+
+        $id = TemplateModel::create($data);
+        if (!empty($data['entities']) && is_array($data['entities'])) {
+            foreach ($data['entities'] as $entity) {
+                TemplateAssociationModel::create(['templateId' => $id, 'entityId' => $entity]);
             }
         }
+        HistoryController::add([
+            'tableName' => 'templates',
+            'recordId'  => $id,
+            'eventType' => 'ADD',
+            'info'      => _TEMPLATE_ADDED . " : {$data['template_label']}",
+            'moduleId'  => 'template',
+            'eventId'   => 'templateCreation',
+        ]);
 
-        return $response->withJson(['templates' => $templates]);
+        return $response->withJson(['template' => $id]);
+    }
+
+    public function update(Request $request, Response $response, array $aArgs)
+    {
+        if (!ServiceModel::hasService(['id' => 'admin_templates', 'userId' => $GLOBALS['userId'], 'location' => 'templates', 'type' => 'admin'])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
+        }
+
+        $data = $request->getParams();
+
+        $check = Validator::stringType()->notEmpty()->validate($data['template_label']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_comment']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_content']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_type']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_datasource']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_target']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['template_attachment_type']);
+        if (!$check) {
+            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
+        }
+
+        $template = TemplateModel::getById(['select' => [1], 'id' => $aArgs['id']]);
+        if (empty($template)) {
+            return $response->withStatus(400)->withJson(['errors' => 'Template does not exist']);
+        }
+
+        TemplateModel::update(['set' => $data, 'where' => ['template_id = ?'], 'data' => [$aArgs['id']]]);
+        if (!empty($data['entities']) && is_array($data['entities'])) {
+            TemplateAssociationModel::delete(['where' => ['template_id = ?'], 'data' => [$aArgs['id']]]);
+            foreach ($data['entities'] as $entity) {
+                TemplateAssociationModel::create(['templateId' => $aArgs['id'], 'entityId' => $entity]);
+            }
+        }
+        HistoryController::add([
+            'tableName' => 'templates',
+            'recordId'  => $aArgs['id'],
+            'eventType' => 'UP',
+            'info'      => _TEMPLATE_UPDATED . " : {$data['template_label']}",
+            'moduleId'  => 'template',
+            'eventId'   => 'templateModification',
+        ]);
+
+        return $response->withJson(['success' => 'success']);
+    }
+
+    public function delete(Request $request, Response $response, array $aArgs)
+    {
+        if (!ServiceModel::hasService(['id' => 'admin_templates', 'userId' => $GLOBALS['userId'], 'location' => 'templates', 'type' => 'admin'])) {
+            return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
+        }
+
+        $template = TemplateModel::getById(['select' => ['template_label'], 'id' => $aArgs['id']]);
+        if (empty($template)) {
+            return $response->withStatus(400)->withJson(['errors' => 'Template does not exist']);
+        }
+
+        TemplateModel::delete(['where' => ['template_id = ?'], 'data' => [$aArgs['id']]]);
+        TemplateAssociationModel::delete(['where' => ['template_id = ?'], 'data' => [$aArgs['id']]]);
+        HistoryController::add([
+            'tableName' => 'templates',
+            'recordId'  => $aArgs['id'],
+            'eventType' => 'DEL',
+            'info'      => _TEMPLATE_DELETED . " : {$template['template_label']}",
+            'moduleId'  => 'template',
+            'eventId'   => 'templateSuppression',
+        ]);
+
+        return $response->withJson(['success' => 'success']);
     }
 
     public function duplicate(Request $request, Response $response, array $aArgs)
diff --git a/src/app/template/models/TemplateAssociationModelAbstract.php b/src/app/template/models/TemplateAssociationModelAbstract.php
index 2b6c4e96391c1d759eec68bae262696dc692ed1c..402b8c3d7263d6aed2ac977ecfc844200d0b2771 100644
--- a/src/app/template/models/TemplateAssociationModelAbstract.php
+++ b/src/app/template/models/TemplateAssociationModelAbstract.php
@@ -36,34 +36,22 @@ abstract class TemplateAssociationModelAbstract
         return $aTemplates;
     }
 
-//    public static function create(array $aArgs)
-//    {
-//        ValidatorModel::notEmpty($aArgs, ['template_label']);
-//        ValidatorModel::stringType($aArgs, ['template_label']);
-//
-//        $nextSequenceId = DatabaseModel::getNextSequenceValue(['sequenceId' => 'templates_seq']);
-//
-//        DatabaseModel::insert(
-//            [
-//                'table'         => 'templates',
-//                'columnsValues' => [
-//                    'template_id'               => $nextSequenceId,
-//                    'template_label'            => $aArgs['template_label'],
-//                    'template_comment'          => $aArgs['template_comment'],
-//                    'template_content'          => $aArgs['template_content'],
-//                    'template_type'             => $aArgs['template_type'],
-//                    'template_style'            => $aArgs['template_style'],
-//                    'template_datasource'       => $aArgs['template_datasource'],
-//                    'template_target'           => $aArgs['template_target'],
-//                    'template_attachment_type'  => $aArgs['template_attachment_type'],
-//                    'template_path'             => $aArgs['template_path'],
-//                    'template_file_name'        => $aArgs['template_file_name'],
-//                ]
-//            ]
-//        );
-//
-//        return $nextSequenceId;
-//    }
+    public static function create(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['entityId', 'templateId']);
+        ValidatorModel::stringType($aArgs, ['entityId']);
+        ValidatorModel::intVal($aArgs, ['templateId']);
+
+        DatabaseModel::insert([
+            'table'         => 'templates_association',
+            'columnsValues' => [
+                'template_id'               => $aArgs['templateId'],
+                'value_field'               => $aArgs['entityId']
+            ]
+        ]);
+
+        return true;
+    }
 
     public static function update(array $aArgs)
     {
@@ -79,4 +67,18 @@ abstract class TemplateAssociationModelAbstract
 
         return true;
     }
+
+    public static function delete(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['where', 'data']);
+        ValidatorModel::arrayType($aArgs, ['where', 'data']);
+
+        DatabaseModel::delete([
+            'table' => 'templates_association',
+            'where' => $aArgs['where'],
+            'data'  => $aArgs['data']
+        ]);
+
+        return true;
+    }
 }
diff --git a/src/app/template/models/TemplateModelAbstract.php b/src/app/template/models/TemplateModelAbstract.php
index 3996a50d1a1cb4c8686e34583910fc1d8de56d18..bbed229bd19f7ef58de9f8c33632878fefffbc71 100644
--- a/src/app/template/models/TemplateModelAbstract.php
+++ b/src/app/template/models/TemplateModelAbstract.php
@@ -76,25 +76,52 @@ abstract class TemplateModelAbstract
 
         $nextSequenceId = DatabaseModel::getNextSequenceValue(['sequenceId' => 'templates_seq']);
 
-        DatabaseModel::insert(
-            [
-                'table'         => 'templates',
-                'columnsValues' => [
-                    'template_id'               => $nextSequenceId,
-                    'template_label'            => $aArgs['template_label'],
-                    'template_comment'          => $aArgs['template_comment'],
-                    'template_content'          => $aArgs['template_content'],
-                    'template_type'             => $aArgs['template_type'],
-                    'template_style'            => $aArgs['template_style'],
-                    'template_datasource'       => $aArgs['template_datasource'],
-                    'template_target'           => $aArgs['template_target'],
-                    'template_attachment_type'  => $aArgs['template_attachment_type'],
-                    'template_path'             => $aArgs['template_path'],
-                    'template_file_name'        => $aArgs['template_file_name'],
-                ]
+        DatabaseModel::insert([
+            'table'         => 'templates',
+            'columnsValues' => [
+                'template_id'               => $nextSequenceId,
+                'template_label'            => $aArgs['template_label'],
+                'template_comment'          => $aArgs['template_comment'],
+                'template_content'          => $aArgs['template_content'],
+                'template_type'             => $aArgs['template_type'],
+                'template_style'            => $aArgs['template_style'],
+                'template_datasource'       => $aArgs['template_datasource'],
+                'template_target'           => $aArgs['template_target'],
+                'template_attachment_type'  => $aArgs['template_attachment_type'],
+                'template_path'             => $aArgs['template_path'],
+                'template_file_name'        => $aArgs['template_file_name'],
             ]
-        );
+        ]);
 
         return $nextSequenceId;
     }
+
+    public static function update(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['set', 'where', 'data']);
+        ValidatorModel::arrayType($aArgs, ['set', 'where', 'data']);
+
+        DatabaseModel::update([
+            'table' => 'templates',
+            'set'   => $aArgs['set'],
+            'where' => $aArgs['where'],
+            'data'  => $aArgs['data']
+        ]);
+
+        return true;
+    }
+
+    public static function delete(array $aArgs)
+    {
+        ValidatorModel::notEmpty($aArgs, ['where', 'data']);
+        ValidatorModel::arrayType($aArgs, ['where', 'data']);
+
+        DatabaseModel::delete([
+            'table' => 'templates',
+            'where' => $aArgs['where'],
+            'data'  => $aArgs['data']
+        ]);
+
+        return true;
+    }
 }
diff --git a/src/core/lang/lang-en.php b/src/core/lang/lang-en.php
index c649c18c597ed013d8dfe0234865eeef7b536d06..5dd1ea6987a57d4f57b83f7352e52a4292f36c1d 100644
--- a/src/core/lang/lang-en.php
+++ b/src/core/lang/lang-en.php
@@ -77,6 +77,9 @@ define('_REPORT_MODIFICATION', 'Report modification');
 define('_STATUS_ADDED', 'Statut added');
 define('_STATUS_DELETED', 'Statut deleted');
 define('_STATUS_NOT_FOUND', 'Status not found');
+define('_TEMPLATE_ADDED', 'Template added');
+define('_TEMPLATE_UPDATED', 'Template updated');
+define('_TEMPLATE_DELETED', 'Template deleted');
 define('_TO_CC', 'On copy');
 define('_TO_SIGN', 'For signature');
 define('_UPDATE_STATUS', 'Status update');
diff --git a/src/core/lang/lang-fr.php b/src/core/lang/lang-fr.php
index 8d00b684e5c12c41d697e1d2fa9abda1a911c980..53f1391abb51e33e13b54782f02c458578e003c0 100644
--- a/src/core/lang/lang-fr.php
+++ b/src/core/lang/lang-fr.php
@@ -77,6 +77,9 @@ define('_REPORT_MODIFICATION', 'Modification états et édition');
 define('_STATUS_ADDED', 'Statut ajouté');
 define('_STATUS_DELETED', 'Statut supprimé');
 define('_STATUS_NOT_FOUND', 'Statut introuvable');
+define('_TEMPLATE_ADDED', 'Modèle de document ajouté');
+define('_TEMPLATE_UPDATED', 'Modèle de document modifié');
+define('_TEMPLATE_DELETED', 'Modèle de document supprimé');
 define('_TO_CC', 'En copie');
 define('_TO_SIGN', 'Pour signature');
 define('_UPDATE_STATUS', 'Modification du statut');