diff --git a/src/Controller/ApiMetaInfoController.php b/src/Controller/ApiMetaInfoController.php
index 8fa4c119a80fe53f74819f573e62d62b9495578c..009a0b33fd97589748eb76dcb0d225fd385f5fc9 100644
--- a/src/Controller/ApiMetaInfoController.php
+++ b/src/Controller/ApiMetaInfoController.php
@@ -30,99 +30,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  */
 class ApiMetaInfoController extends ApiBaseController
 {
-    /**
-     *
-     * Crée un modèle de méta-information.
-     *
-     * @Route("/create-template", name="api_meta_info_template_create", methods={"POST"})
-     *
-     * @OA\Response(response=200, description="success", @OA\JsonContent(type="string"))
-     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
-     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
-     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
-     * @OA\RequestBody(
-     *     required=true,
-     *     @OA\JsonContent(
-     *       required={"description", "category"},
-     *       @OA\Property(property="description", type="string", example="Nombre de fois où a été rencontré dans MW"),
-     *       @OA\Property(property="category", type="string", example="integer OR string OR boolean"),
-     *       @OA\Property(property="default", type="string", example="10 OR true OR false OR string value"),
-     *       @OA\Property(property="choices", type="array", description="Optionnel. Tableau des valeurs possibles quand category = string",
-     *             example={"connu", "non connu"},
-     *             @OA\Items(
-     *                 type="string"
-     *             )
-     *         )
-     *     )
-     * )
-     * @OA\Tag(name="MetaInfos")
-     * @Security(name="OAuth2")
-     */
-    public function createMetaInfoTemplate(Request $request): Response
-    {
-        $data = json_decode($request->getContent(), true);
-        if (!$data) {
-            return $this->createJsonResponse(401, ['error' => sprintf("Json non valide")]);
-        }
-        if ($missingFields = $this->getMissingFields($data, ['description', 'category'])) {
-            return $this->createJsonResponse(401, ['error' => sprintf("Veuillez fournir une valeur pour: %s", implode(', ', $missingFields))]);
-        }
-        if (!in_array($data['category'], MetaInfo::META_INFO_LIST_CATEGORIES)) {
-            return $this->createJsonResponse(401, ['error' => sprintf("La catégorie de méta-information %s n'existe pas", $data['category'])]);
-        }
-
-        $metaInfoTemplate = new MetaInfoTemplate($data['category']);
-        $metaInfoTemplate->setCreatedBy($this->getUser());
-        $metaInfoTemplate->setDescription($data['description']);
-        if ($data['default'] ?? null) {
-            $metaInfoTemplate->setDefault($data['default']);
-        }
-        if ($data['choices'] ?? null && $data['category'] === MetaInfo::META_INFO_CATEGORY_STRING) {
-            if (is_array($data['choices'])) {
-                $metaInfoTemplate->setComplementStringChoices($data['choices']);
-            } else {
-                return $this->createJsonResponse(401, ['error' => sprintf("Le paramètre choices doit être un tableau")]);
-            }
-        }
-        $this->doctrine->getManager()->persist($metaInfoTemplate);
-        $this->doctrine->getManager()->flush();
-
-        $this->success[] = sprintf("Modèle de Méta information id %s créé.", $metaInfoTemplate->getId());
-
-        return $this->createJsonResponse(200);
-    }
-
-    /**
-     * Supprime le metaInfoTemplate
-     *
-     * @Route("/delete-template/{id}", name="api_meta_info_template_delete", methods={"DELETE"})
-     *
-     * @OA\Response(
-     *     response=200,
-     *     description="Success"
-     * )
-     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
-     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
-     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
-     *
-     * @OA\Parameter(
-     *     name="id",
-     *     in="path",
-     *     description="id of the meta info template to be removed",
-     *     @OA\Schema(type="integer")
-     * )
-     * @OA\Tag(name="MetaInfos")
-     * @Security(name="OAuth2")
-     */
-    public function delete(MetaInfoTemplate $metaInfoTemplate)
-    {
-        $response = $this->createJsonResponse(200, ['success' => sprintf("Modèle de Méta information « %s » (id: %s) supprimé", $metaInfoTemplate->getDescription(), $metaInfoTemplate->getId())]);
-        $this->doctrine->getManager()->remove($metaInfoTemplate);
-        $this->doctrine->getManager()->flush();
-
-        return $response;
-    }
-
     /**
      *
      * Si la graphie possède déjà une méta information de la même catégorie que le modèle template_id, on la met à jour sinon on crée une nouvelle méta-info.
@@ -193,22 +100,22 @@ class ApiMetaInfoController extends ApiBaseController
     }
 
     /**
-     * Recherche de metaInfos par date ou user ou action ou origin
+     * Recherche de metaInfos id graphie ou id de modèle méta information
      *
      * @Route("/search", name="api_meta_info_search", methods={"POST"})
      *
-     * @OA\Response(response=200, description="success", @OA\JsonContent(type="string"))
+     * @OA\Response(response=200, description="success",
+     *      @OA\JsonContent(type="array",
+     *          @OA\Items(ref=@Model(type=MetaInfo::class, groups={"metaInfo:read"})))
+     * )
      * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
      * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
      * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
      * @OA\RequestBody(
      *     required=true,
      *     @OA\JsonContent(
-     *         @OA\Property(property="date", type="date"),
-     *         @OA\Property(property="date_client", type="date"),
-     *         @OA\Property(property="user_id", type="integer", example="4"),
-     *         @OA\Property(property="origin", type="string", example="Prisms"),
-     *         @OA\Property(property="action", type="string", example="action"),
+     *         @OA\Property(property="graphy_id", type="integer"),
+     *         @OA\Property(property="template_id", type="integer")
      *     )
      * )
      * @OA\Tag(name="MetaInfos")
@@ -220,46 +127,22 @@ class ApiMetaInfoController extends ApiBaseController
         if (!$data) {
             return $this->createJsonResponse(401, ['error' => sprintf("Json non valide")]);
         }
-        if (!isset($data['date']) && !isset($data['date_client']) && !isset($data['user_id']) && !isset($data['origin']) && !isset($data['action'])) {
-            return $this->createJsonResponse(401, ['error' => sprintf("Veuillez spécifier au moins un paramètre de recherche parmi: date, user_id, action, origin")]);
+        if (!isset($data['date']) && !isset($data['graphy_id']) && !isset($data['template_id'])) {
+            return $this->createJsonResponse(401, ['error' => sprintf("Veuillez spécifier au moins un paramètre de recherche parmi: graphy_id, template_id")]);
         }
 
         $filter = [];
-        if ($data['date'] ?? null) {
-            $date = date_create_from_format('Y-m-d', $data['date']);
-            if ($date === false) {
-                return $this->createJsonResponse(401, ['error' => sprintf("Veuillez fournir une date au format aaaa-mm-jj pour le paramètre «date»")]);
-            } else {
-                $filter['date'] = $date;
-            }
-        }
-        if ($data['date_client'] ?? null) {
-            $dateClient = date_create_from_format('Y-m-d', $data['date_client']);
-            if ($dateClient === false) {
-                return $this->createJsonResponse(401, ['error' => sprintf("Veuillez fournir une date au format aaaa-mm-jj pour le paramètre «date client»")]);
-            } else {
-                $filter['date_client'] = $dateClient;
-            }
-        }
-        if ($data["user_id"] ?? null) {
-            $user = $this->doctrine->getRepository(User::class)->find($data['user_id']);
-            if (!$user) {
-                return $this->createJsonResponse(401, ['error' => sprintf("Pas d'utilisateur trouvé pour l'id %s", $data['user_id'])]);
-            } else {
-                $filter['user'] = $user;
-            }
-        }
-        if ($data['origin'] ?? null) {
-            $filter['origin'] = $data['origin'];
+        if ($data['graphy_id'] ?? null) {
+            $filter['graphy'] = $data['graphy_id'];
         }
-        if ($data['action'] ?? null) {
-            $filter['action'] = $data['action'];
+        if ($data['template_id'] ?? null) {
+            $filter['metaInfoTemplate'] = $data['template_id'];
         }
 
-        $metaInfos = $this->doctrine->getRepository(MetaInfo::class)->search($filter);
+        $metaInfos = $this->doctrine->getRepository(MetaInfo::class)->findBy($filter, ['createdAt' => 'DESC']);
 
         $content = $serializer->serialize($metaInfos, 'json', [
-            'groups' => ["metaInfo:read"],
+            'groups' => ["metaInfo:read", "user:read"],
             'datetime_format' => 'Y-m-d h:i:s.u'
         ]);
 
diff --git a/src/Controller/ApiMetaInfoTemplateController.php b/src/Controller/ApiMetaInfoTemplateController.php
new file mode 100644
index 0000000000000000000000000000000000000000..7b1be999cb0ed06d6c1ff2f330d8b4af9a001410
--- /dev/null
+++ b/src/Controller/ApiMetaInfoTemplateController.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace App\Controller;
+
+use App\Entity\Entry;
+use App\Entity\Graphy;
+use App\Entity\Headword;
+use App\Entity\Label;
+use App\Entity\Lexicon;
+use App\Entity\MetaInfo;
+use App\Entity\MetaInfoTemplate;
+use App\Entity\User;
+use App\Manager\WiktionaryManager;
+use App\Repository\LabelRepository;
+use Doctrine\Persistence\ManagerRegistry;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Annotation\Route;
+use Nelmio\ApiDocBundle\Annotation\Security;
+use OpenApi\Annotations as OA;
+use Nelmio\ApiDocBundle\Annotation\Model;
+use Symfony\Component\Serializer\SerializerInterface;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
+
+/**
+ * @Route("/api/meta-info-template")
+ */
+class ApiMetaInfoTemplateController extends ApiBaseController
+{
+    /**
+     *
+     * Crée un modèle de méta-information.
+     *
+     * @Route("/create", name="api_meta_info_template_create", methods={"POST"})
+     *
+     * @OA\Response(response=200, description="success", @OA\JsonContent(type="string"))
+     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
+     * @OA\RequestBody(
+     *     required=true,
+     *     @OA\JsonContent(
+     *       required={"description", "category"},
+     *       @OA\Property(property="description", type="string", example="Nombre de fois où a été rencontré dans MW"),
+     *       @OA\Property(property="category", type="string", example="integer OR string OR boolean"),
+     *       @OA\Property(property="default", type="string", example="10 OR true OR false OR string value"),
+     *       @OA\Property(property="choices", type="array", description="Optionnel. Tableau des valeurs possibles quand category = string",
+     *             example={"connu", "non connu"},
+     *             @OA\Items(
+     *                 type="string"
+     *             )
+     *         )
+     *     )
+     * )
+     * @OA\Tag(name="MetaInfoTemplates")
+     * @Security(name="OAuth2")
+     */
+    public function createMetaInfoTemplate(Request $request): Response
+    {
+        $data = json_decode($request->getContent(), true);
+        if (!$data) {
+            return $this->createJsonResponse(401, ['error' => sprintf("Json non valide")]);
+        }
+        if ($missingFields = $this->getMissingFields($data, ['description', 'category'])) {
+            return $this->createJsonResponse(401, ['error' => sprintf("Veuillez fournir une valeur pour: %s", implode(', ', $missingFields))]);
+        }
+        if (!in_array($data['category'], MetaInfo::META_INFO_LIST_CATEGORIES)) {
+            return $this->createJsonResponse(401, ['error' => sprintf("La catégorie de méta-information %s n'existe pas", $data['category'])]);
+        }
+
+        $metaInfoTemplate = new MetaInfoTemplate($data['category']);
+        $metaInfoTemplate->setCreatedBy($this->getUser());
+        $metaInfoTemplate->setDescription($data['description']);
+        if ($data['default'] ?? null) {
+            $metaInfoTemplate->setDefault($data['default']);
+        }
+        if ($data['choices'] ?? null && $data['category'] === MetaInfo::META_INFO_CATEGORY_STRING) {
+            if (is_array($data['choices'])) {
+                $metaInfoTemplate->setComplementStringChoices($data['choices']);
+            } else {
+                return $this->createJsonResponse(401, ['error' => sprintf("Le paramètre choices doit être un tableau")]);
+            }
+        }
+        $this->doctrine->getManager()->persist($metaInfoTemplate);
+        $this->doctrine->getManager()->flush();
+
+        $this->success[] = sprintf("Modèle de Méta information id %s créé.", $metaInfoTemplate->getId());
+
+        return $this->createJsonResponse(200);
+    }
+
+    /**
+     * Supprime le metaInfoTemplate
+     *
+     * @Route("/delete/{id}", name="api_meta_info_template_delete", methods={"DELETE"})
+     *
+     * @OA\Response(
+     *     response=200,
+     *     description="Success"
+     * )
+     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
+     *
+     * @OA\Parameter(
+     *     name="id",
+     *     in="path",
+     *     description="id of the meta info template to be removed",
+     *     @OA\Schema(type="integer")
+     * )
+     * @OA\Tag(name="MetaInfoTemplates")
+     * @Security(name="OAuth2")
+     */
+    public function delete(MetaInfoTemplate $metaInfoTemplate)
+    {
+        $response = $this->createJsonResponse(200, ['success' => sprintf("Modèle de Méta information « %s » (id: %s) supprimé", $metaInfoTemplate->getDescription(), $metaInfoTemplate->getId())]);
+        $this->doctrine->getManager()->remove($metaInfoTemplate);
+        $this->doctrine->getManager()->flush();
+
+        return $response;
+    }
+
+    /**
+     * Permet de modifier un modèle de méta information existant. On n'autorise pas la modification de la catégorie
+     *
+     * @Route("/edit/{id}", name="api_meta_info_template_edit", methods={"POST"})
+     *
+     * @OA\Response(response=200, description="success", @OA\JsonContent(type="string"))
+     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
+     *
+     * @OA\Parameter(
+     *     name="id",
+     *     in="path",
+     *     description="id of the meta info template",
+     *     @OA\Schema(type="integer")
+     * )
+     * @OA\RequestBody(
+     *     required=true,
+     *     @OA\JsonContent(
+     *       @OA\Property(property="description", type="string", example="Nombre de fois où a été rencontré dans MW"),
+     *       @OA\Property(property="default", type="string", example="10 OR true OR false OR string value"),
+     *       @OA\Property(property="choices", type="array", description="Optionnel. Tableau des valeurs possibles quand category = string",
+     *             example={"connu", "non connu"},
+     *             @OA\Items(
+     *                 type="string"
+     *             )
+     *         )
+     *     )
+     * )
+     * @OA\Tag(name="MetaInfoTemplates")
+     * @Security(name="OAuth2")
+     */
+    public function editMetaInfoTemplate(Request $request, MetaInfoTemplate $metaInfoTemplate = null): Response
+    {
+        if (!$metaInfoTemplate) {
+            return $this->createJsonResponse(401, ['error' => sprintf("Pas de modèle trouvé pour cette id")]);
+        }
+        $data = json_decode($request->getContent(), true);
+        if (!$data) {
+            return $this->createJsonResponse(401, ['error' => sprintf("Json non valide")]);
+        }
+
+        if ($data['description'] ?? null) {
+            $metaInfoTemplate->setDescription($data['description']);
+        }
+        if ($data['default'] ?? null) {
+            $metaInfoTemplate->setDefault($data['default']);
+        }
+        if ($data['choices'] ?? null && $data['category'] === MetaInfo::META_INFO_CATEGORY_STRING) {
+            if (is_array($data['choices'])) {
+                $metaInfoTemplate->setComplementStringChoices($data['choices']);
+            } else {
+                return $this->createJsonResponse(401, ['error' => sprintf("Le paramètre choices doit être un tableau")]);
+            }
+        }
+
+        $this->doctrine->getManager()->flush();
+
+        return $this->createJsonResponse(200, ['message' => sprintf("Modèle « %s » mis à jour.", $metaInfoTemplate)]);
+    }
+
+    /**
+     * Liste tous les modèles existants
+     *
+     * @Route("/list", name="api_meta_info_template_list", methods={"GET"})
+     *
+     * @OA\Response(response=200, description="success",
+     *      @OA\JsonContent(type="array",
+     *          @OA\Items(ref=@Model(type=MetaInfoTemplate::class, groups={"metaInfo:read"})))
+     * )
+     * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
+     * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
+     *
+     * @OA\Tag(name="MetaInfoTemplates")
+     * @Security(name="OAuth2")
+     */
+    public function listMetaInfoTemplates(Request $request, SerializerInterface $serializer): Response
+    {
+        $metaInfoTemplates = $this->doctrine->getRepository(MetaInfoTemplate::class)->findAll();
+
+        $content = $serializer->serialize($metaInfoTemplates, 'json', ['groups' => ["metaInfo:read", "user:read"]]);
+
+        return new JsonResponse($content, 200, [], true);
+    }
+
+}
diff --git a/src/Controller/ApiTraceController.php b/src/Controller/ApiTraceController.php
index 67c63ae8bc80746aadc8e9a5536dc13418c1101a..6767f7a98b734ee636786fe324677711b94287c8 100644
--- a/src/Controller/ApiTraceController.php
+++ b/src/Controller/ApiTraceController.php
@@ -153,7 +153,10 @@ class ApiTraceController extends ApiBaseController
      *
      * @Route("/search", name="api_trace_search", methods={"POST"})
      *
-     * @OA\Response(response=200, description="success", @OA\JsonContent(type="string"))
+     * @OA\Response(response=200, description="success",
+     *      @OA\JsonContent(type="array",
+     *          @OA\Items(ref=@Model(type=Trace::class, groups={"trace:read"})))
+     * )
      * @OA\Response(response=401, description="error", @OA\JsonContent(type="string"))
      * @OA\Response(response=403, description="error", @OA\JsonContent(type="string"))
      * @OA\Response(response=500, description="error", @OA\JsonContent(type="string"))
@@ -215,7 +218,7 @@ class ApiTraceController extends ApiBaseController
         $traces = $this->doctrine->getRepository(Trace::class)->search($filter);
 
         $content = $serializer->serialize($traces, 'json', [
-            'groups' => ["trace:read"],
+            'groups' => ["trace:read", "user:read"],
             'datetime_format' => 'Y-m-d h:i:s.u'
         ]);
 
diff --git a/src/Entity/MetaInfo.php b/src/Entity/MetaInfo.php
index f4154bf2a2622ac400a099bad941b9ba25514d7d..2950fdb0f6d2fb4c65e910e35c6ffc4f3a26393f 100644
--- a/src/Entity/MetaInfo.php
+++ b/src/Entity/MetaInfo.php
@@ -29,6 +29,7 @@ class MetaInfo
      * @ORM\Id
      * @ORM\GeneratedValue
      * @ORM\Column(type="integer")
+     * @Groups({"metaInfo:read"})
      */
     private $id;
 
diff --git a/src/Entity/MetaInfoTemplate.php b/src/Entity/MetaInfoTemplate.php
index 93be2e79aa4a4bd5fdb2a1d4a3cd8d6c1aa58c87..15826ad6fee87167bbf8865ec288e278d0c24e84 100644
--- a/src/Entity/MetaInfoTemplate.php
+++ b/src/Entity/MetaInfoTemplate.php
@@ -18,6 +18,7 @@ class MetaInfoTemplate
     /**
      * @ORM\Id
      * @ORM\GeneratedValue
+     * @Groups({"metaInfo:read"})
      * @ORM\Column(type="integer")
      */
     private $id;
@@ -60,6 +61,7 @@ class MetaInfoTemplate
     /**
      * @ORM\Column(type="array", nullable=true)
      * @Groups({"metaInfo:read"})
+     * @OA\Property(type="array", @OA\Items(type="string"))
      */
     private $complementStringChoices;
 
diff --git a/src/Entity/Trace.php b/src/Entity/Trace.php
index 663a15131119ae816937289af0bad423a47ab513..b6be20dc85b21116c680e9f6340403292e263dc2 100644
--- a/src/Entity/Trace.php
+++ b/src/Entity/Trace.php
@@ -22,12 +22,14 @@ class Trace
     private $id;
 
     /**
+     * @var \DateTimeImmutable
      * @Groups({"trace:read"})
      * @ORM\Column(type="datetimemicroseconds")
      */
     private $createdAt;
 
     /**
+     * @var \DateTime
      * @Groups({"trace:read"})
      * @ORM\Column(type="datetimemicroseconds")
      */
diff --git a/src/Entity/User.php b/src/Entity/User.php
index 27c07ad18ab9b8f5996b9e34781ceeed2d0ca2a6..3d844f9c6889a577b10bd9b177e3083bf9f80c77 100644
--- a/src/Entity/User.php
+++ b/src/Entity/User.php
@@ -37,6 +37,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
      * @ORM\Id
      * @ORM\GeneratedValue
      * @ORM\Column(type="integer")
+     * @Groups({"user:read"})
      */
     private $id;
 
@@ -60,6 +61,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
      * @var string
      * @ORM\Column(type="string", length=100)
      * @Assert\Length(max={100})
+     * @Groups({"user:read"})
      */
     private $pseudo;