Repository: quantori/quantori-pesn-python-sdk (language: python)

Issue:
SBT-64 Add Logging for BioSequence, Sample, SamplesContainer + docs



Discussion / hints:

Fix patch:
diff --git a/docs/signals_notebook/api.html b/docs/signals_notebook/api.html
index 2e97850f..c4dbc70a 100644
--- a/docs/signals_notebook/api.html
+++ b/docs/signals_notebook/api.html
@@ -27,6 +27,7 @@ <h1 class="title">Module <code>signals_notebook.api</code></h1>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">import logging
+from enum import Enum
 from typing import Any, Dict, IO, Iterable, Mapping, Optional, Sequence, Tuple, Union
 
 import requests
@@ -148,6 +149,10 @@ <h1 class="title">Module <code>signals_notebook.api</code></h1>
 
         headers = {**self.HTTP_DEFAULT_HEADERS, **headers}
 
+        for key, value in headers.items():
+            if isinstance(value, Enum):
+                headers[key] = value.value
+
         if json:
             response = self._session.request(
                 method=method,
@@ -323,6 +328,10 @@ <h2 class="section-title" id="header-classes">Classes</h2>
 
         headers = {**self.HTTP_DEFAULT_HEADERS, **headers}
 
+        for key, value in headers.items():
+            if isinstance(value, Enum):
+                headers[key] = value.value
+
         if json:
             response = self._session.request(
                 method=method,
@@ -550,6 +559,10 @@ <h2 id="returns">Returns</h2>
 
     headers = {**self.HTTP_DEFAULT_HEADERS, **headers}
 
+    for key, value in headers.items():
+        if isinstance(value, Enum):
+            headers[key] = value.value
+
     if json:
         response = self._session.request(
             method=method,
diff --git a/docs/signals_notebook/attributes/attribute.html b/docs/signals_notebook/attributes/attribute.html
index 6c23e381..042e0a2c 100644
--- a/docs/signals_notebook/attributes/attribute.html
+++ b/docs/signals_notebook/attributes/attribute.html
@@ -27,24 +27,63 @@ <h1 class="title">Module <code>signals_notebook.attributes.attribute</code></h1>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">import logging
-from typing import cast, List, Literal
+from enum import Enum
+from typing import cast, Generator, Literal, Optional
 
 from pydantic import BaseModel
+from pydantic.fields import PrivateAttr
 
 from signals_notebook.api import SignalsNotebookApi
-from signals_notebook.common_types import AttrID, Response, ResponseData
+from signals_notebook.common_types import AttrID, ObjectType, Response, ResponseData
 
 log = logging.getLogger(__name__)
 
 
+class Action(str, Enum):
+    UPDATE = &#39;update&#39;
+    DELETE = &#39;delete&#39;
+    CREATE = &#39;create&#39;
+
+
+class _Attributes(BaseModel):
+    action: Action
+    value: Optional[str]
+
+
+class _OptionRepresentation(BaseModel):
+    id: Optional[str]
+    type: Literal[ObjectType.ATTRIBUTE_OPTION] = ObjectType.ATTRIBUTE_OPTION
+    attributes: _Attributes
+
+
+class _AttributeOption(BaseModel):
+    value: str
+
+
+class _AttributeOptionResponse(Response[_AttributeOption]):
+    pass
+
+
 class Attribute(BaseModel):
-    type: Literal[&#39;choice&#39;]
+    type: str
     id: AttrID
     name: str
-    options: List[str]
+    _options: list[str] = PrivateAttr(default=[])
 
-    class Meta:
-        frozen = True
+    def __init__(self, *args, **kwargs):
+        self._options = kwargs.pop(&#39;options&#39;, [])
+        super().__init__(*args, **kwargs)
+        self.type = ObjectType.CHOICE
+
+    def __iter__(self):
+        if not self._options:
+            self._reload_options()
+        return self._options.__iter__()
+
+    def __len__(self) -&gt; int:
+        if not self._options:
+            self._reload_options()
+        return len(self._options)
 
     @classmethod
     def _get_endpoint(cls) -&gt; str:
@@ -67,17 +106,177 @@ <h1 class="title">Module <code>signals_notebook.attributes.attribute</code></h1>
             path=(cls._get_endpoint(), id),
         )
 
-        result = Response[cls](**response.json())  # type: ignore
+        result = AttributeResponse(**response.json())
         log.debug(&#39;Get Attribute with ID: %s&#39;, id)
 
         return cast(ResponseData, result.data).body
 
-    def __call__(self, value: str) -&gt; str:
-        if value not in self.options:
-            log.exception(&#39;Incorrect attribute value&#39;)
-            raise ValueError(&#39;Incorrect attribute value&#39;)
+    @classmethod
+    def get_list(cls) -&gt; Generator[&#39;Attribute&#39;, None, None]:
+        &#34;&#34;&#34;Get all Attributes.
+
+        Returns:
+           list of available Attributes
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Get List of Attributes&#39;)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(cls._get_endpoint(),),
+        )
+        result = AttributeResponse(**response.json())
+
+        yield from [cast(ResponseData, item).body for item in result.data]
+
+        while result.links and result.links.next:
+            response = api.call(
+                method=&#39;GET&#39;,
+                path=result.links.next,
+            )
+
+            result = AttributeResponse(**response.json())
+            yield from [cast(ResponseData, item).body for item in result.data]
+
+        log.debug(&#39;List of Attributes was got successfully.&#39;)
+
+    @classmethod
+    def create(
+        cls,
+        name: str,
+        description: str,
+        options: list[str] = None,
+    ) -&gt; &#39;Attribute&#39;:
+        &#34;&#34;&#34;Create new Attribute
+
+        Args:
+            name: name of new Attribute
+            description: description of new Attribute
+            options: list of available id options for created Attribute
+
+        Returns:
+            Attribute
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+
+        log.debug(&#39;Create Attribute: %s...&#39;, cls.__name__)
+
+        response = api.call(
+            method=&#39;POST&#39;,
+            path=(cls._get_endpoint(),),
+            json={
+                &#39;data&#39;: {
+                    &#39;type&#39;: ObjectType.ATTRIBUTE,
+                    &#39;attributes&#39;: {
+                        &#39;name&#39;: name,
+                        &#39;type&#39;: ObjectType.CHOICE,
+                        &#39;description&#39;: description,
+                        &#39;options&#39;: options or [],
+                    },
+                }
+            },
+        )
+        log.debug(&#39;Attribute: %s was created.&#39;, cls.__name__)
+
+        result = AttributeResponse(**response.json())
+        return cast(ResponseData, result.data).body
+
+    def delete(self) -&gt; None:
+        &#34;&#34;&#34;Delete an Attribute by id.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Delete Attribute: %s...&#39;, self.id)
+
+        api.call(
+            method=&#39;DELETE&#39;,
+            path=(self._get_endpoint(), self.id),
+        )
+        log.debug(&#39;Attribute: %s was deleted successfully&#39;, self.id)
+
+    def add_option(self, option: str) -&gt; None:
+        &#34;&#34;&#34;Update option of Attribute by id.
+
+        Args:
+            option: option which will be added to option list in Attribute
+
+        Returns:
+
+        &#34;&#34;&#34;
+        new_option = _OptionRepresentation(attributes=_Attributes(action=Action.CREATE, value=option))
+        log.debug(&#39;Creating Option: %s...&#39;, self.id)
+        self._patch_options(new_option)
+
+    def delete_option(self, option: str) -&gt; None:
+        &#34;&#34;&#34;Delete option of Attribute by id.
+
+        Args:
+            option: option which will be deleted from Attribute&#39;s option list
+
+        Returns:
+
+        &#34;&#34;&#34;
+        deleted_option = _OptionRepresentation(id=option, attributes=_Attributes(action=Action.DELETE))
+        log.debug(&#39;Deleting Option: %s...&#39;, self.id)
+        self._patch_options(deleted_option)
+
+    def update_option(self, old_option: str, new_option: str) -&gt; None:
+        &#34;&#34;&#34;Update option of Attribute by id.
+
+        Args:
+            old_option: old option which will be updated
+            new_option: new option value
+
+        Returns:
 
-        return value</code></pre>
+        &#34;&#34;&#34;
+        option = _OptionRepresentation(id=old_option, attributes=_Attributes(action=Action.UPDATE, value=new_option))
+        log.debug(&#39;Patching Option: %s...&#39;, self.id)
+        self._patch_options(option)
+
+    def _patch_options(self, option: _OptionRepresentation) -&gt; None:
+        api = SignalsNotebookApi.get_default_api()
+        api.call(
+            method=&#39;PATCH&#39;,
+            path=(self._get_endpoint(), self.id, &#39;options&#39;),
+            json={&#39;data&#39;: [option.dict(exclude_none=True)]},
+        )
+        self._reload_options()
+        log.debug(&#39;Attribute: %s was reloaded successfully&#39;, self.id)
+
+    def _reload_options(self):
+        self._options = []
+        api = SignalsNotebookApi.get_default_api()
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(self._get_endpoint(), self.id, &#39;options&#39;),
+        )
+
+        result = _AttributeOptionResponse(**response.json())
+
+        for item in result.data:
+            body = cast(ResponseData, item).body
+            option = cast(_AttributeOption, body)
+
+            self._options.append(option.value)
+
+    @property
+    def options(self) -&gt; list[str]:
+        &#34;&#34;&#34;Get Attribute options
+
+        Returns:
+            list[str]
+        &#34;&#34;&#34;
+        if not self._options:
+            self._reload_options()
+        return self._options
+
+
+class AttributeResponse(Response[Attribute]):
+    pass</code></pre>
 </details>
 </section>
 <section>
@@ -89,9 +288,45 @@ <h1 class="title">Module <code>signals_notebook.attributes.attribute</code></h1>
 <section>
 <h2 class="section-title" id="header-classes">Classes</h2>
 <dl>
+<dt id="signals_notebook.attributes.attribute.Action"><code class="flex name class">
+<span>class <span class="ident">Action</span></span>
+<span>(</span><span>value, names=None, *, module=None, qualname=None, type=None, start=1)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>An enumeration.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class Action(str, Enum):
+    UPDATE = &#39;update&#39;
+    DELETE = &#39;delete&#39;
+    CREATE = &#39;create&#39;</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>builtins.str</li>
+<li>enum.Enum</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.Action.CREATE"><code class="name">var <span class="ident">CREATE</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Action.DELETE"><code class="name">var <span class="ident">DELETE</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Action.UPDATE"><code class="name">var <span class="ident">UPDATE</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
 <dt id="signals_notebook.attributes.attribute.Attribute"><code class="flex name class">
 <span>class <span class="ident">Attribute</span></span>
-<span>(</span><span>**data: Any)</span>
+<span>(</span><span>*args, **kwargs)</span>
 </code></dt>
 <dd>
 <div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
@@ -101,13 +336,25 @@ <h2 class="section-title" id="header-classes">Classes</h2>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">class Attribute(BaseModel):
-    type: Literal[&#39;choice&#39;]
+    type: str
     id: AttrID
     name: str
-    options: List[str]
+    _options: list[str] = PrivateAttr(default=[])
 
-    class Meta:
-        frozen = True
+    def __init__(self, *args, **kwargs):
+        self._options = kwargs.pop(&#39;options&#39;, [])
+        super().__init__(*args, **kwargs)
+        self.type = ObjectType.CHOICE
+
+    def __iter__(self):
+        if not self._options:
+            self._reload_options()
+        return self._options.__iter__()
+
+    def __len__(self) -&gt; int:
+        if not self._options:
+            self._reload_options()
+        return len(self._options)
 
     @classmethod
     def _get_endpoint(cls) -&gt; str:
@@ -130,17 +377,173 @@ <h2 class="section-title" id="header-classes">Classes</h2>
             path=(cls._get_endpoint(), id),
         )
 
-        result = Response[cls](**response.json())  # type: ignore
+        result = AttributeResponse(**response.json())
         log.debug(&#39;Get Attribute with ID: %s&#39;, id)
 
         return cast(ResponseData, result.data).body
 
-    def __call__(self, value: str) -&gt; str:
-        if value not in self.options:
-            log.exception(&#39;Incorrect attribute value&#39;)
-            raise ValueError(&#39;Incorrect attribute value&#39;)
+    @classmethod
+    def get_list(cls) -&gt; Generator[&#39;Attribute&#39;, None, None]:
+        &#34;&#34;&#34;Get all Attributes.
+
+        Returns:
+           list of available Attributes
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Get List of Attributes&#39;)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(cls._get_endpoint(),),
+        )
+        result = AttributeResponse(**response.json())
+
+        yield from [cast(ResponseData, item).body for item in result.data]
+
+        while result.links and result.links.next:
+            response = api.call(
+                method=&#39;GET&#39;,
+                path=result.links.next,
+            )
+
+            result = AttributeResponse(**response.json())
+            yield from [cast(ResponseData, item).body for item in result.data]
+
+        log.debug(&#39;List of Attributes was got successfully.&#39;)
+
+    @classmethod
+    def create(
+        cls,
+        name: str,
+        description: str,
+        options: list[str] = None,
+    ) -&gt; &#39;Attribute&#39;:
+        &#34;&#34;&#34;Create new Attribute
+
+        Args:
+            name: name of new Attribute
+            description: description of new Attribute
+            options: list of available id options for created Attribute
 
-        return value</code></pre>
+        Returns:
+            Attribute
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+
+        log.debug(&#39;Create Attribute: %s...&#39;, cls.__name__)
+
+        response = api.call(
+            method=&#39;POST&#39;,
+            path=(cls._get_endpoint(),),
+            json={
+                &#39;data&#39;: {
+                    &#39;type&#39;: ObjectType.ATTRIBUTE,
+                    &#39;attributes&#39;: {
+                        &#39;name&#39;: name,
+                        &#39;type&#39;: ObjectType.CHOICE,
+                        &#39;description&#39;: description,
+                        &#39;options&#39;: options or [],
+                    },
+                }
+            },
+        )
+        log.debug(&#39;Attribute: %s was created.&#39;, cls.__name__)
+
+        result = AttributeResponse(**response.json())
+        return cast(ResponseData, result.data).body
+
+    def delete(self) -&gt; None:
+        &#34;&#34;&#34;Delete an Attribute by id.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Delete Attribute: %s...&#39;, self.id)
+
+        api.call(
+            method=&#39;DELETE&#39;,
+            path=(self._get_endpoint(), self.id),
+        )
+        log.debug(&#39;Attribute: %s was deleted successfully&#39;, self.id)
+
+    def add_option(self, option: str) -&gt; None:
+        &#34;&#34;&#34;Update option of Attribute by id.
+
+        Args:
+            option: option which will be added to option list in Attribute
+
+        Returns:
+
+        &#34;&#34;&#34;
+        new_option = _OptionRepresentation(attributes=_Attributes(action=Action.CREATE, value=option))
+        log.debug(&#39;Creating Option: %s...&#39;, self.id)
+        self._patch_options(new_option)
+
+    def delete_option(self, option: str) -&gt; None:
+        &#34;&#34;&#34;Delete option of Attribute by id.
+
+        Args:
+            option: option which will be deleted from Attribute&#39;s option list
+
+        Returns:
+
+        &#34;&#34;&#34;
+        deleted_option = _OptionRepresentation(id=option, attributes=_Attributes(action=Action.DELETE))
+        log.debug(&#39;Deleting Option: %s...&#39;, self.id)
+        self._patch_options(deleted_option)
+
+    def update_option(self, old_option: str, new_option: str) -&gt; None:
+        &#34;&#34;&#34;Update option of Attribute by id.
+
+        Args:
+            old_option: old option which will be updated
+            new_option: new option value
+
+        Returns:
+
+        &#34;&#34;&#34;
+        option = _OptionRepresentation(id=old_option, attributes=_Attributes(action=Action.UPDATE, value=new_option))
+        log.debug(&#39;Patching Option: %s...&#39;, self.id)
+        self._patch_options(option)
+
+    def _patch_options(self, option: _OptionRepresentation) -&gt; None:
+        api = SignalsNotebookApi.get_default_api()
+        api.call(
+            method=&#39;PATCH&#39;,
+            path=(self._get_endpoint(), self.id, &#39;options&#39;),
+            json={&#39;data&#39;: [option.dict(exclude_none=True)]},
+        )
+        self._reload_options()
+        log.debug(&#39;Attribute: %s was reloaded successfully&#39;, self.id)
+
+    def _reload_options(self):
+        self._options = []
+        api = SignalsNotebookApi.get_default_api()
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(self._get_endpoint(), self.id, &#39;options&#39;),
+        )
+
+        result = _AttributeOptionResponse(**response.json())
+
+        for item in result.data:
+            body = cast(ResponseData, item).body
+            option = cast(_AttributeOption, body)
+
+            self._options.append(option.value)
+
+    @property
+    def options(self) -&gt; list[str]:
+        &#34;&#34;&#34;Get Attribute options
+
+        Returns:
+            list[str]
+        &#34;&#34;&#34;
+        if not self._options:
+            self._reload_options()
+        return self._options</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -149,10 +552,6 @@ <h3>Ancestors</h3>
 </ul>
 <h3>Class variables</h3>
 <dl>
-<dt id="signals_notebook.attributes.attribute.Attribute.Meta"><code class="name">var <span class="ident">Meta</span></code></dt>
-<dd>
-<div class="desc"></div>
-</dd>
 <dt id="signals_notebook.attributes.attribute.Attribute.id"><code class="name">var <span class="ident">id</span> : <a title="signals_notebook.common_types.AttrID" href="../common_types.html#signals_notebook.common_types.AttrID">AttrID</a></code></dt>
 <dd>
 <div class="desc"></div>
@@ -161,17 +560,75 @@ <h3>Class variables</h3>
 <dd>
 <div class="desc"></div>
 </dd>
-<dt id="signals_notebook.attributes.attribute.Attribute.options"><code class="name">var <span class="ident">options</span> : List[str]</code></dt>
-<dd>
-<div class="desc"></div>
-</dd>
-<dt id="signals_notebook.attributes.attribute.Attribute.type"><code class="name">var <span class="ident">type</span> : Literal['choice']</code></dt>
+<dt id="signals_notebook.attributes.attribute.Attribute.type"><code class="name">var <span class="ident">type</span> : str</code></dt>
 <dd>
 <div class="desc"></div>
 </dd>
 </dl>
 <h3>Static methods</h3>
 <dl>
+<dt id="signals_notebook.attributes.attribute.Attribute.create"><code class="name flex">
+<span>def <span class="ident">create</span></span>(<span>name: str, description: str, options: list = None) ‑> <a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a></span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create new Attribute</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>name</code></strong></dt>
+<dd>name of new Attribute</dd>
+<dt><strong><code>description</code></strong></dt>
+<dd>description of new Attribute</dd>
+<dt><strong><code>options</code></strong></dt>
+<dd>list of available id options for created Attribute</dd>
+</dl>
+<h2 id="returns">Returns</h2>
+<p>Attribute</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def create(
+    cls,
+    name: str,
+    description: str,
+    options: list[str] = None,
+) -&gt; &#39;Attribute&#39;:
+    &#34;&#34;&#34;Create new Attribute
+
+    Args:
+        name: name of new Attribute
+        description: description of new Attribute
+        options: list of available id options for created Attribute
+
+    Returns:
+        Attribute
+    &#34;&#34;&#34;
+    api = SignalsNotebookApi.get_default_api()
+
+    log.debug(&#39;Create Attribute: %s...&#39;, cls.__name__)
+
+    response = api.call(
+        method=&#39;POST&#39;,
+        path=(cls._get_endpoint(),),
+        json={
+            &#39;data&#39;: {
+                &#39;type&#39;: ObjectType.ATTRIBUTE,
+                &#39;attributes&#39;: {
+                    &#39;name&#39;: name,
+                    &#39;type&#39;: ObjectType.CHOICE,
+                    &#39;description&#39;: description,
+                    &#39;options&#39;: options or [],
+                },
+            }
+        },
+    )
+    log.debug(&#39;Attribute: %s was created.&#39;, cls.__name__)
+
+    result = AttributeResponse(**response.json())
+    return cast(ResponseData, result.data).body</code></pre>
+</details>
+</dd>
 <dt id="signals_notebook.attributes.attribute.Attribute.get"><code class="name flex">
 <span>def <span class="ident">get</span></span>(<span>id: <a title="signals_notebook.common_types.AttrID" href="../common_types.html#signals_notebook.common_types.AttrID">AttrID</a>) ‑> <a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a></span>
 </code></dt>
@@ -205,12 +662,301 @@ <h2 id="returns">Returns</h2>
         path=(cls._get_endpoint(), id),
     )
 
-    result = Response[cls](**response.json())  # type: ignore
+    result = AttributeResponse(**response.json())
     log.debug(&#39;Get Attribute with ID: %s&#39;, id)
 
     return cast(ResponseData, result.data).body</code></pre>
 </details>
 </dd>
+<dt id="signals_notebook.attributes.attribute.Attribute.get_list"><code class="name flex">
+<span>def <span class="ident">get_list</span></span>(<span>) ‑> Generator[<a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a>, None, None]</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get all Attributes.</p>
+<h2 id="returns">Returns</h2>
+<p>list of available Attributes</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def get_list(cls) -&gt; Generator[&#39;Attribute&#39;, None, None]:
+    &#34;&#34;&#34;Get all Attributes.
+
+    Returns:
+       list of available Attributes
+    &#34;&#34;&#34;
+    api = SignalsNotebookApi.get_default_api()
+    log.debug(&#39;Get List of Attributes&#39;)
+
+    response = api.call(
+        method=&#39;GET&#39;,
+        path=(cls._get_endpoint(),),
+    )
+    result = AttributeResponse(**response.json())
+
+    yield from [cast(ResponseData, item).body for item in result.data]
+
+    while result.links and result.links.next:
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=result.links.next,
+        )
+
+        result = AttributeResponse(**response.json())
+        yield from [cast(ResponseData, item).body for item in result.data]
+
+    log.debug(&#39;List of Attributes was got successfully.&#39;)</code></pre>
+</details>
+</dd>
+</dl>
+<h3>Instance variables</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.Attribute.options"><code class="name">var <span class="ident">options</span> : list</code></dt>
+<dd>
+<div class="desc"><p>Get Attribute options</p>
+<h2 id="returns">Returns</h2>
+<p>list[str]</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@property
+def options(self) -&gt; list[str]:
+    &#34;&#34;&#34;Get Attribute options
+
+    Returns:
+        list[str]
+    &#34;&#34;&#34;
+    if not self._options:
+        self._reload_options()
+    return self._options</code></pre>
+</details>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.Attribute.add_option"><code class="name flex">
+<span>def <span class="ident">add_option</span></span>(<span>self, option: str) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Update option of Attribute by id.</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>option</code></strong></dt>
+<dd>option which will be added to option list in Attribute</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def add_option(self, option: str) -&gt; None:
+    &#34;&#34;&#34;Update option of Attribute by id.
+
+    Args:
+        option: option which will be added to option list in Attribute
+
+    Returns:
+
+    &#34;&#34;&#34;
+    new_option = _OptionRepresentation(attributes=_Attributes(action=Action.CREATE, value=option))
+    log.debug(&#39;Creating Option: %s...&#39;, self.id)
+    self._patch_options(new_option)</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Attribute.delete"><code class="name flex">
+<span>def <span class="ident">delete</span></span>(<span>self) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Delete an Attribute by id.</p>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def delete(self) -&gt; None:
+    &#34;&#34;&#34;Delete an Attribute by id.
+
+    Returns:
+
+    &#34;&#34;&#34;
+    api = SignalsNotebookApi.get_default_api()
+    log.debug(&#39;Delete Attribute: %s...&#39;, self.id)
+
+    api.call(
+        method=&#39;DELETE&#39;,
+        path=(self._get_endpoint(), self.id),
+    )
+    log.debug(&#39;Attribute: %s was deleted successfully&#39;, self.id)</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Attribute.delete_option"><code class="name flex">
+<span>def <span class="ident">delete_option</span></span>(<span>self, option: str) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Delete option of Attribute by id.</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>option</code></strong></dt>
+<dd>option which will be deleted from Attribute's option list</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def delete_option(self, option: str) -&gt; None:
+    &#34;&#34;&#34;Delete option of Attribute by id.
+
+    Args:
+        option: option which will be deleted from Attribute&#39;s option list
+
+    Returns:
+
+    &#34;&#34;&#34;
+    deleted_option = _OptionRepresentation(id=option, attributes=_Attributes(action=Action.DELETE))
+    log.debug(&#39;Deleting Option: %s...&#39;, self.id)
+    self._patch_options(deleted_option)</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Attribute.update_option"><code class="name flex">
+<span>def <span class="ident">update_option</span></span>(<span>self, old_option: str, new_option: str) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Update option of Attribute by id.</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>old_option</code></strong></dt>
+<dd>old option which will be updated</dd>
+<dt><strong><code>new_option</code></strong></dt>
+<dd>new option value</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def update_option(self, old_option: str, new_option: str) -&gt; None:
+    &#34;&#34;&#34;Update option of Attribute by id.
+
+    Args:
+        old_option: old option which will be updated
+        new_option: new option value
+
+    Returns:
+
+    &#34;&#34;&#34;
+    option = _OptionRepresentation(id=old_option, attributes=_Attributes(action=Action.UPDATE, value=new_option))
+    log.debug(&#39;Patching Option: %s...&#39;, self.id)
+    self._patch_options(option)</code></pre>
+</details>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.attributes.attribute.AttributeResponse"><code class="flex name class">
+<span>class <span class="ident">AttributeResponse</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class AttributeResponse(Response[Attribute]):
+    pass</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.attributes.attribute.Response[Attribute]" href="#signals_notebook.attributes.attribute.Response[Attribute]">Response[Attribute]</a></li>
+<li><a title="signals_notebook.common_types.Response" href="../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.AttributeResponse.data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[<a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a>], List[pydantic.generics.ResponseData[<a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a>]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.AttributeResponse.links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[Attribute]"><code class="flex name class">
+<span>class <span class="ident">Response[Attribute]</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.common_types.Response" href="../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Subclasses</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.attributes.attribute.AttributeResponse" href="#signals_notebook.attributes.attribute.AttributeResponse">AttributeResponse</a></li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.Response[Attribute].Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[Attribute].data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[<a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a>], List[pydantic.generics.ResponseData[<a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a>]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[Attribute].links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[_AttributeOption]"><code class="flex name class">
+<span>class <span class="ident">Response[_AttributeOption]</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.common_types.Response" href="../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Subclasses</h3>
+<ul class="hlist">
+<li>signals_notebook.attributes.attribute._AttributeOptionResponse</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.attributes.attribute.Response[_AttributeOption].Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[_AttributeOption].data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[_AttributeOption], List[pydantic.generics.ResponseData[_AttributeOption]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.attributes.attribute.Response[_AttributeOption].links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 </dl>
 </dd>
 </dl>
@@ -230,14 +976,50 @@ <h1>Index</h1>
 <li><h3><a href="#header-classes">Classes</a></h3>
 <ul>
 <li>
+<h4><code><a title="signals_notebook.attributes.attribute.Action" href="#signals_notebook.attributes.attribute.Action">Action</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.attributes.attribute.Action.CREATE" href="#signals_notebook.attributes.attribute.Action.CREATE">CREATE</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Action.DELETE" href="#signals_notebook.attributes.attribute.Action.DELETE">DELETE</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Action.UPDATE" href="#signals_notebook.attributes.attribute.Action.UPDATE">UPDATE</a></code></li>
+</ul>
+</li>
+<li>
 <h4><code><a title="signals_notebook.attributes.attribute.Attribute" href="#signals_notebook.attributes.attribute.Attribute">Attribute</a></code></h4>
 <ul class="two-column">
-<li><code><a title="signals_notebook.attributes.attribute.Attribute.Meta" href="#signals_notebook.attributes.attribute.Attribute.Meta">Meta</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.add_option" href="#signals_notebook.attributes.attribute.Attribute.add_option">add_option</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.create" href="#signals_notebook.attributes.attribute.Attribute.create">create</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.delete" href="#signals_notebook.attributes.attribute.Attribute.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.delete_option" href="#signals_notebook.attributes.attribute.Attribute.delete_option">delete_option</a></code></li>
 <li><code><a title="signals_notebook.attributes.attribute.Attribute.get" href="#signals_notebook.attributes.attribute.Attribute.get">get</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.get_list" href="#signals_notebook.attributes.attribute.Attribute.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.attributes.attribute.Attribute.id" href="#signals_notebook.attributes.attribute.Attribute.id">id</a></code></li>
 <li><code><a title="signals_notebook.attributes.attribute.Attribute.name" href="#signals_notebook.attributes.attribute.Attribute.name">name</a></code></li>
 <li><code><a title="signals_notebook.attributes.attribute.Attribute.options" href="#signals_notebook.attributes.attribute.Attribute.options">options</a></code></li>
 <li><code><a title="signals_notebook.attributes.attribute.Attribute.type" href="#signals_notebook.attributes.attribute.Attribute.type">type</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Attribute.update_option" href="#signals_notebook.attributes.attribute.Attribute.update_option">update_option</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.attributes.attribute.AttributeResponse" href="#signals_notebook.attributes.attribute.AttributeResponse">AttributeResponse</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.attributes.attribute.AttributeResponse.data" href="#signals_notebook.attributes.attribute.AttributeResponse.data">data</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.AttributeResponse.links" href="#signals_notebook.attributes.attribute.AttributeResponse.links">links</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.attributes.attribute.Response[Attribute]" href="#signals_notebook.attributes.attribute.Response[Attribute]">Response[Attribute]</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.attributes.attribute.Response[Attribute].Config" href="#signals_notebook.attributes.attribute.Response[Attribute].Config">Config</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Response[Attribute].data" href="#signals_notebook.attributes.attribute.Response[Attribute].data">data</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Response[Attribute].links" href="#signals_notebook.attributes.attribute.Response[Attribute].links">links</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.attributes.attribute.Response[_AttributeOption]" href="#signals_notebook.attributes.attribute.Response[_AttributeOption]">Response[_AttributeOption]</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.attributes.attribute.Response[_AttributeOption].Config" href="#signals_notebook.attributes.attribute.Response[_AttributeOption].Config">Config</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Response[_AttributeOption].data" href="#signals_notebook.attributes.attribute.Response[_AttributeOption].data">data</a></code></li>
+<li><code><a title="signals_notebook.attributes.attribute.Response[_AttributeOption].links" href="#signals_notebook.attributes.attribute.Response[_AttributeOption].links">links</a></code></li>
 </ul>
 </li>
 </ul>
diff --git a/docs/signals_notebook/common_types.html b/docs/signals_notebook/common_types.html
index 1baa4d7a..691ee441 100644
--- a/docs/signals_notebook/common_types.html
+++ b/docs/signals_notebook/common_types.html
@@ -67,6 +67,9 @@ <h1 class="title">Module <code>signals_notebook.common_types</code></h1>
     PROFILE = &#39;profile&#39;
     GROUP = &#39;group&#39;
     ROLE = &#39;role&#39;
+    PLATE_ROW = &#39;plateRow&#39;
+    ATTRIBUTE_OPTION = &#39;option&#39;
+    CHOICE = &#39;choice&#39;
 
 
 class EntityType(str, Enum):
@@ -87,6 +90,8 @@ <h1 class="title">Module <code>signals_notebook.common_types</code></h1>
     SPOTFIRE = &#39;spotfiredxp&#39;
     TODO_LIST = &#39;linkedTaskContainer&#39;
     TASK = &#39;task&#39;
+    PLATE_CONTAINER = &#39;plateContainer&#39;
+    MATERIAL_TABLE = &#39;materialsTable&#39;
 
 
 class MaterialType(str, Enum):
@@ -1061,7 +1066,9 @@ <h3>Class variables</h3>
     POWER_POINT = &#39;presentation&#39;
     SPOTFIRE = &#39;spotfiredxp&#39;
     TODO_LIST = &#39;linkedTaskContainer&#39;
-    TASK = &#39;task&#39;</code></pre>
+    TASK = &#39;task&#39;
+    PLATE_CONTAINER = &#39;plateContainer&#39;
+    MATERIAL_TABLE = &#39;materialsTable&#39;</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -1098,10 +1105,18 @@ <h3>Class variables</h3>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt id="signals_notebook.common_types.EntityType.MATERIAL_TABLE"><code class="name">var <span class="ident">MATERIAL_TABLE</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt id="signals_notebook.common_types.EntityType.NOTEBOOK"><code class="name">var <span class="ident">NOTEBOOK</span></code></dt>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt id="signals_notebook.common_types.EntityType.PLATE_CONTAINER"><code class="name">var <span class="ident">PLATE_CONTAINER</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt id="signals_notebook.common_types.EntityType.POWER_POINT"><code class="name">var <span class="ident">POWER_POINT</span></code></dt>
 <dd>
 <div class="desc"></div>
@@ -1652,7 +1667,10 @@ <h3>Class variables</h3>
     USER = &#39;user&#39;
     PROFILE = &#39;profile&#39;
     GROUP = &#39;group&#39;
-    ROLE = &#39;role&#39;</code></pre>
+    ROLE = &#39;role&#39;
+    PLATE_ROW = &#39;plateRow&#39;
+    ATTRIBUTE_OPTION = &#39;option&#39;
+    CHOICE = &#39;choice&#39;</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -1673,6 +1691,14 @@ <h3>Class variables</h3>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt id="signals_notebook.common_types.ObjectType.ATTRIBUTE_OPTION"><code class="name">var <span class="ident">ATTRIBUTE_OPTION</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.common_types.ObjectType.CHOICE"><code class="name">var <span class="ident">CHOICE</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt id="signals_notebook.common_types.ObjectType.COLUMN_DEFINITIONS"><code class="name">var <span class="ident">COLUMN_DEFINITIONS</span></code></dt>
 <dd>
 <div class="desc"></div>
@@ -1689,6 +1715,10 @@ <h3>Class variables</h3>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt id="signals_notebook.common_types.ObjectType.PLATE_ROW"><code class="name">var <span class="ident">PLATE_ROW</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt id="signals_notebook.common_types.ObjectType.PROFILE"><code class="name">var <span class="ident">PROFILE</span></code></dt>
 <dd>
 <div class="desc"></div>
@@ -1746,13 +1776,17 @@ <h3>Ancestors</h3>
 </ul>
 <h3>Subclasses</h3>
 <ul class="hlist">
+<li><a title="signals_notebook.attributes.attribute.Response[Attribute]" href="attributes/attribute.html#signals_notebook.attributes.attribute.Response[Attribute]">Response[Attribute]</a></li>
+<li><a title="signals_notebook.attributes.attribute.Response[_AttributeOption]" href="attributes/attribute.html#signals_notebook.attributes.attribute.Response[_AttributeOption]">Response[_AttributeOption]</a></li>
 <li><a title="signals_notebook.entities.entity.Response[Property]" href="entities/entity.html#signals_notebook.entities.entity.Response[Property]">Response[Property]</a></li>
+<li><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow]" href="entities/plates/plate_container.html#signals_notebook.entities.plates.plate_container.Response[PlateRow]">Response[PlateRow]</a></li>
 <li><a title="signals_notebook.entities.samples.sample.Response[SampleCell]" href="entities/samples/sample.html#signals_notebook.entities.samples.sample.Response[SampleCell]">Response[SampleCell]</a></li>
 <li><a title="signals_notebook.entities.samples.samples_container.Response[Sample]" href="entities/samples/samples_container.html#signals_notebook.entities.samples.samples_container.Response[Sample]">Response[Sample]</a></li>
 <li><a title="signals_notebook.entities.stoichiometry.stoichiometry.Response[ColumnDefinitions]" href="entities/stoichiometry/stoichiometry.html#signals_notebook.entities.stoichiometry.stoichiometry.Response[ColumnDefinitions]">Response[ColumnDefinitions]</a></li>
 <li><a title="signals_notebook.entities.stoichiometry.stoichiometry.Response[DataGrids]" href="entities/stoichiometry/stoichiometry.html#signals_notebook.entities.stoichiometry.stoichiometry.Response[DataGrids]">Response[DataGrids]</a></li>
 <li><a title="signals_notebook.entities.tables.table.Response[ColumnDefinitions]" href="entities/tables/table.html#signals_notebook.entities.tables.table.Response[ColumnDefinitions]">Response[ColumnDefinitions]</a></li>
 <li><a title="signals_notebook.entities.tables.table.Response[Row]" href="entities/tables/table.html#signals_notebook.entities.tables.table.Response[Row]">Response[Row]</a></li>
+<li><a title="signals_notebook.entities.tables.table.Response[Table]" href="entities/tables/table.html#signals_notebook.entities.tables.table.Response[Table]">Response[Table]</a></li>
 <li><a title="signals_notebook.entities.todo_list.task.Response[TaskCell]" href="entities/todo_list/task.html#signals_notebook.entities.todo_list.task.Response[TaskCell]">Response[TaskCell]</a></li>
 <li><a title="signals_notebook.materials.asset.Response[Batch]" href="materials/asset.html#signals_notebook.materials.asset.Response[Batch]">Response[Batch]</a></li>
 <li><a title="signals_notebook.materials.library.Response[Asset]" href="materials/library.html#signals_notebook.materials.library.Response[Asset]">Response[Asset]</a></li>
@@ -1811,20 +1845,24 @@ <h3>Ancestors</h3>
 <h3>Subclasses</h3>
 <ul class="hlist">
 <li>pydantic.generics.ResponseData[Asset]</li>
+<li>pydantic.generics.ResponseData[Attribute]</li>
 <li>pydantic.generics.ResponseData[Batch]</li>
 <li>pydantic.generics.ResponseData[ColumnDefinitions]</li>
 <li>pydantic.generics.ResponseData[ColumnDefinitions]</li>
 <li>pydantic.generics.ResponseData[DataGrids]</li>
 <li>pydantic.generics.ResponseData[Group]</li>
+<li>pydantic.generics.ResponseData[PlateRow]</li>
 <li>pydantic.generics.ResponseData[Profile]</li>
 <li>pydantic.generics.ResponseData[Property]</li>
 <li>pydantic.generics.ResponseData[Role]</li>
 <li>pydantic.generics.ResponseData[Row]</li>
 <li>pydantic.generics.ResponseData[SampleCell]</li>
 <li>pydantic.generics.ResponseData[Sample]</li>
+<li>pydantic.generics.ResponseData[Table]</li>
 <li>pydantic.generics.ResponseData[TaskCell]</li>
 <li>pydantic.generics.ResponseData[Union[Library, Asset, Batch]]</li>
 <li>pydantic.generics.ResponseData[User]</li>
+<li>pydantic.generics.ResponseData[_AttributeOption]</li>
 <li>pydantic.generics.ResponseData[_LibraryListData]</li>
 </ul>
 <h3>Class variables</h3>
@@ -1979,7 +2017,9 @@ <h4><code><a title="signals_notebook.common_types.EntityType" href="#signals_not
 <li><code><a title="signals_notebook.common_types.EntityType.EXPERIMENT" href="#signals_notebook.common_types.EntityType.EXPERIMENT">EXPERIMENT</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.GRID" href="#signals_notebook.common_types.EntityType.GRID">GRID</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.IMAGE_RESOURCE" href="#signals_notebook.common_types.EntityType.IMAGE_RESOURCE">IMAGE_RESOURCE</a></code></li>
+<li><code><a title="signals_notebook.common_types.EntityType.MATERIAL_TABLE" href="#signals_notebook.common_types.EntityType.MATERIAL_TABLE">MATERIAL_TABLE</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.NOTEBOOK" href="#signals_notebook.common_types.EntityType.NOTEBOOK">NOTEBOOK</a></code></li>
+<li><code><a title="signals_notebook.common_types.EntityType.PLATE_CONTAINER" href="#signals_notebook.common_types.EntityType.PLATE_CONTAINER">PLATE_CONTAINER</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.POWER_POINT" href="#signals_notebook.common_types.EntityType.POWER_POINT">POWER_POINT</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.SAMPLE" href="#signals_notebook.common_types.EntityType.SAMPLE">SAMPLE</a></code></li>
 <li><code><a title="signals_notebook.common_types.EntityType.SAMPLES_CONTAINER" href="#signals_notebook.common_types.EntityType.SAMPLES_CONTAINER">SAMPLES_CONTAINER</a></code></li>
@@ -2035,10 +2075,13 @@ <h4><code><a title="signals_notebook.common_types.ObjectType" href="#signals_not
 <li><code><a title="signals_notebook.common_types.ObjectType.ADT_ROW" href="#signals_notebook.common_types.ObjectType.ADT_ROW">ADT_ROW</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.ASSET_TYPE" href="#signals_notebook.common_types.ObjectType.ASSET_TYPE">ASSET_TYPE</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.ATTRIBUTE" href="#signals_notebook.common_types.ObjectType.ATTRIBUTE">ATTRIBUTE</a></code></li>
+<li><code><a title="signals_notebook.common_types.ObjectType.ATTRIBUTE_OPTION" href="#signals_notebook.common_types.ObjectType.ATTRIBUTE_OPTION">ATTRIBUTE_OPTION</a></code></li>
+<li><code><a title="signals_notebook.common_types.ObjectType.CHOICE" href="#signals_notebook.common_types.ObjectType.CHOICE">CHOICE</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.COLUMN_DEFINITIONS" href="#signals_notebook.common_types.ObjectType.COLUMN_DEFINITIONS">COLUMN_DEFINITIONS</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.ENTITY" href="#signals_notebook.common_types.ObjectType.ENTITY">ENTITY</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.GROUP" href="#signals_notebook.common_types.ObjectType.GROUP">GROUP</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.MATERIAL" href="#signals_notebook.common_types.ObjectType.MATERIAL">MATERIAL</a></code></li>
+<li><code><a title="signals_notebook.common_types.ObjectType.PLATE_ROW" href="#signals_notebook.common_types.ObjectType.PLATE_ROW">PLATE_ROW</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.PROFILE" href="#signals_notebook.common_types.ObjectType.PROFILE">PROFILE</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.PROPERTY" href="#signals_notebook.common_types.ObjectType.PROPERTY">PROPERTY</a></code></li>
 <li><code><a title="signals_notebook.common_types.ObjectType.ROLE" href="#signals_notebook.common_types.ObjectType.ROLE">ROLE</a></code></li>
diff --git a/docs/signals_notebook/entities/biological_sequence.html b/docs/signals_notebook/entities/biological_sequence.html
index b964713b..3d880176 100644
--- a/docs/signals_notebook/entities/biological_sequence.html
+++ b/docs/signals_notebook/entities/biological_sequence.html
@@ -306,6 +306,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/chemical_drawing.html b/docs/signals_notebook/entities/chemical_drawing.html
index 9d4a19b8..7a0fb6c2 100644
--- a/docs/signals_notebook/entities/chemical_drawing.html
+++ b/docs/signals_notebook/entities/chemical_drawing.html
@@ -39,6 +39,7 @@ <h1 class="title">Module <code>signals_notebook.entities.chemical_drawing</code>
 from signals_notebook.entities.contentful_entity import ContentfulEntity
 from signals_notebook.entities.stoichiometry.stoichiometry import Stoichiometry
 from signals_notebook.jinja_env import env
+from signals_notebook.utils import FSHandler
 
 log = logging.getLogger(__name__)
 
@@ -131,7 +132,31 @@ <h1 class="title">Module <code>signals_notebook.entities.chemical_drawing</code>
         template = env.get_template(self._template_name)
         log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
 
-        return template.render(data=data)</code></pre>
+        return template.render(data=data)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump ChemicalDrawing templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+        try:
+            for template in templates:
+                template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+        except TypeError:
+            pass</code></pre>
 </details>
 </section>
 <section>
@@ -242,7 +267,31 @@ <h2 class="section-title" id="header-classes">Classes</h2>
         template = env.get_template(self._template_name)
         log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
 
-        return template.render(data=data)</code></pre>
+        return template.render(data=data)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump ChemicalDrawing templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+        try:
+            for template in templates:
+                template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+        except TypeError:
+            pass</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -322,6 +371,48 @@ <h2 id="returns">Returns</h2>
     )</code></pre>
 </details>
 </dd>
+<dt id="signals_notebook.entities.chemical_drawing.ChemicalDrawing.dump_templates"><code class="name flex">
+<span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Dump ChemicalDrawing templates</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create templates dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump ChemicalDrawing templates
+
+    Args:
+        base_path: content path where create templates dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
+    from signals_notebook.entities import EntityStore
+
+    entity_type = cls._get_entity_type()
+
+    templates = EntityStore.get_list(
+        include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+    )
+    try:
+        for template in templates:
+            template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+    except TypeError:
+        pass</code></pre>
+</details>
+</dd>
 </dl>
 <h3>Instance variables</h3>
 <dl>
@@ -435,9 +526,10 @@ <h1>Index</h1>
 <ul>
 <li>
 <h4><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing">ChemicalDrawing</a></code></h4>
-<ul class="">
+<ul class="two-column">
 <li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.Config" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.Config">Config</a></code></li>
 <li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.create" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.create">create</a></code></li>
+<li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.dump_templates" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.get_content" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.get_content">get_content</a></code></li>
 <li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.stoichiometry" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.stoichiometry">stoichiometry</a></code></li>
 <li><code><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing.type" href="#signals_notebook.entities.chemical_drawing.ChemicalDrawing.type">type</a></code></li>
diff --git a/docs/signals_notebook/entities/container.html b/docs/signals_notebook/entities/container.html
index 62304160..d8d7fc7e 100644
--- a/docs/signals_notebook/entities/container.html
+++ b/docs/signals_notebook/entities/container.html
@@ -126,7 +126,31 @@ <h1 class="title">Module <code>signals_notebook.entities.container</code></h1>
             json.dumps({k: v for k, v in self.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)}),
         )
         for child in self.get_children():
-            child.dump(fs_handler.join_path(base_path, self.eid), fs_handler)</code></pre>
+            child.dump(fs_handler.join_path(base_path, self.eid), fs_handler)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Container templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+        try:
+            for template in templates:
+                template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+        except TypeError:
+            pass</code></pre>
 </details>
 </section>
 <section>
@@ -234,7 +258,31 @@ <h2 class="section-title" id="header-classes">Classes</h2>
             json.dumps({k: v for k, v in self.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)}),
         )
         for child in self.get_children():
-            child.dump(fs_handler.join_path(base_path, self.eid), fs_handler)</code></pre>
+            child.dump(fs_handler.join_path(base_path, self.eid), fs_handler)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Container templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+        try:
+            for template in templates:
+                template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+        except TypeError:
+            pass</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -279,6 +327,51 @@ <h3>Class variables</h3>
 <div class="desc"></div>
 </dd>
 </dl>
+<h3>Static methods</h3>
+<dl>
+<dt id="signals_notebook.entities.container.Container.dump_templates"><code class="name flex">
+<span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Dump Container templates</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create templates dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump Container templates
+
+    Args:
+        base_path: content path where create templates dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
+    from signals_notebook.entities import EntityStore
+
+    entity_type = cls._get_entity_type()
+
+    templates = EntityStore.get_list(
+        include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+    )
+    try:
+        for template in templates:
+            template.dump(fs_handler.join_path(base_path, &#39;templates&#39;, entity_type), fs_handler)
+    except TypeError:
+        pass</code></pre>
+</details>
+</dd>
+</dl>
 <h3>Methods</h3>
 <dl>
 <dt id="signals_notebook.entities.container.Container.add_child"><code class="name flex">
@@ -448,6 +541,7 @@ <h4><code><a title="signals_notebook.entities.container.Container" href="#signal
 <li><code><a title="signals_notebook.entities.container.Container.description" href="#signals_notebook.entities.container.Container.description">description</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.digest" href="#signals_notebook.entities.container.Container.digest">digest</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.dump" href="#signals_notebook.entities.container.Container.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.container.Container.dump_templates" href="#signals_notebook.entities.container.Container.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.edited_at" href="#signals_notebook.entities.container.Container.edited_at">edited_at</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.eid" href="#signals_notebook.entities.container.Container.eid">eid</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_children" href="#signals_notebook.entities.container.Container.get_children">get_children</a></code></li>
diff --git a/docs/signals_notebook/entities/contentful_entity.html b/docs/signals_notebook/entities/contentful_entity.html
index c23701bd..ef4f863b 100644
--- a/docs/signals_notebook/entities/contentful_entity.html
+++ b/docs/signals_notebook/entities/contentful_entity.html
@@ -285,10 +285,11 @@ <h3>Subclasses</h3>
 <li><a title="signals_notebook.entities.chemical_drawing.ChemicalDrawing" href="chemical_drawing.html#signals_notebook.entities.chemical_drawing.ChemicalDrawing">ChemicalDrawing</a></li>
 <li><a title="signals_notebook.entities.excel.Excel" href="excel.html#signals_notebook.entities.excel.Excel">Excel</a></li>
 <li><a title="signals_notebook.entities.image.Image" href="image.html#signals_notebook.entities.image.Image">Image</a></li>
+<li><a title="signals_notebook.entities.materials_table.MaterialsTable" href="materials_table.html#signals_notebook.entities.materials_table.MaterialsTable">MaterialsTable</a></li>
+<li><a title="signals_notebook.entities.plates.plate_container.PlateContainer" href="plates/plate_container.html#signals_notebook.entities.plates.plate_container.PlateContainer">PlateContainer</a></li>
 <li><a title="signals_notebook.entities.power_point.PowerPoint" href="power_point.html#signals_notebook.entities.power_point.PowerPoint">PowerPoint</a></li>
 <li><a title="signals_notebook.entities.samples.samples_container.SamplesContainer" href="samples/samples_container.html#signals_notebook.entities.samples.samples_container.SamplesContainer">SamplesContainer</a></li>
 <li><a title="signals_notebook.entities.spotfire.Spotfire" href="spotfire.html#signals_notebook.entities.spotfire.Spotfire">Spotfire</a></li>
-<li><a title="signals_notebook.entities.tables.table.Table" href="tables/table.html#signals_notebook.entities.tables.table.Table">Table</a></li>
 <li><a title="signals_notebook.entities.text.Text" href="text.html#signals_notebook.entities.text.Text">Text</a></li>
 <li><a title="signals_notebook.entities.todo_list.todo_list.TodoList" href="todo_list/todo_list.html#signals_notebook.entities.todo_list.todo_list.TodoList">TodoList</a></li>
 <li><a title="signals_notebook.entities.uploaded_resource.UploadedResource" href="uploaded_resource.html#signals_notebook.entities.uploaded_resource.UploadedResource">UploadedResource</a></li>
@@ -484,6 +485,7 @@ <h3>Inherited members</h3>
 <li><code><b><a title="signals_notebook.entities.entity.Entity" href="entity.html#signals_notebook.entities.entity.Entity">Entity</a></b></code>:
 <ul class="hlist">
 <li><code><a title="signals_notebook.entities.entity.Entity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_template_name" href="entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
diff --git a/docs/signals_notebook/entities/entity.html b/docs/signals_notebook/entities/entity.html
index f0a9c49f..1443d5eb 100644
--- a/docs/signals_notebook/entities/entity.html
+++ b/docs/signals_notebook/entities/entity.html
@@ -338,7 +338,16 @@ <h1 class="title">Module <code>signals_notebook.entities.entity</code></h1>
         log.error(&#39;Loading Entity: not implemented!&#39;)
 
     @classmethod
-    def dump_templates(cls, base_path: str, fs_handler: FSHandler):
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Entity templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
         from signals_notebook.entities import EntityStore
 
         entity_type = cls._get_entity_type()
@@ -615,7 +624,16 @@ <h2 class="section-title" id="header-classes">Classes</h2>
         log.error(&#39;Loading Entity: not implemented!&#39;)
 
     @classmethod
-    def dump_templates(cls, base_path: str, fs_handler: FSHandler):
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Entity templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
         from signals_notebook.entities import EntityStore
 
         entity_type = cls._get_entity_type()
@@ -642,6 +660,7 @@ <h3>Subclasses</h3>
 <li><a title="signals_notebook.entities.container.Container" href="container.html#signals_notebook.entities.container.Container">Container</a></li>
 <li><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></li>
 <li><a title="signals_notebook.entities.samples.sample.Sample" href="samples/sample.html#signals_notebook.entities.samples.sample.Sample">Sample</a></li>
+<li><a title="signals_notebook.entities.tables.table.Table" href="tables/table.html#signals_notebook.entities.tables.table.Table">Table</a></li>
 <li><a title="signals_notebook.entities.todo_list.task.Task" href="todo_list/task.html#signals_notebook.entities.todo_list.task.Task">Task</a></li>
 </ul>
 <h3>Class variables</h3>
@@ -682,16 +701,33 @@ <h3>Class variables</h3>
 <h3>Static methods</h3>
 <dl>
 <dt id="signals_notebook.entities.entity.Entity.dump_templates"><code class="name flex">
-<span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>)</span>
+<span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Dump Entity templates</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create templates dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@classmethod
-def dump_templates(cls, base_path: str, fs_handler: FSHandler):
+def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump Entity templates
+
+    Args:
+        base_path: content path where create templates dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
     from signals_notebook.entities import EntityStore
 
     entity_type = cls._get_entity_type()
diff --git a/docs/signals_notebook/entities/entity_store.html b/docs/signals_notebook/entities/entity_store.html
index dd04c29a..3b2a15dc 100644
--- a/docs/signals_notebook/entities/entity_store.html
+++ b/docs/signals_notebook/entities/entity_store.html
@@ -189,6 +189,15 @@ <h1 class="title">Module <code>signals_notebook.entities.entity_store</code></h1
 
     @classmethod
     def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump all templates from system
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
 
         for item in Entity.get_subclasses():
             item.dump_templates(base_path, fs_handler)</code></pre>
@@ -361,6 +370,15 @@ <h2 class="section-title" id="header-classes">Classes</h2>
 
     @classmethod
     def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump all templates from system
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
 
         for item in Entity.get_subclasses():
             item.dump_templates(base_path, fs_handler)</code></pre>
@@ -427,13 +445,30 @@ <h2 id="args">Args</h2>
 <span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Dump all templates from system</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create templates dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@classmethod
 def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump all templates from system
+
+    Args:
+        base_path: content path where create templates dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
 
     for item in Entity.get_subclasses():
         item.dump_templates(base_path, fs_handler)</code></pre>
diff --git a/docs/signals_notebook/entities/excel.html b/docs/signals_notebook/entities/excel.html
index 031874df..120540fe 100644
--- a/docs/signals_notebook/entities/excel.html
+++ b/docs/signals_notebook/entities/excel.html
@@ -275,6 +275,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/experiment.html b/docs/signals_notebook/entities/experiment.html
index 20ba446c..1d4559c5 100644
--- a/docs/signals_notebook/entities/experiment.html
+++ b/docs/signals_notebook/entities/experiment.html
@@ -547,6 +547,7 @@ <h3>Inherited members</h3>
 <ul class="hlist">
 <li><code><a title="signals_notebook.entities.container.Container.add_child" href="container.html#signals_notebook.entities.container.Container.add_child">add_child</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.container.Container.dump_templates" href="container.html#signals_notebook.entities.container.Container.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_children" href="container.html#signals_notebook.entities.container.Container.get_children">get_children</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/image.html b/docs/signals_notebook/entities/image.html
index e7db7a26..17e22a8c 100644
--- a/docs/signals_notebook/entities/image.html
+++ b/docs/signals_notebook/entities/image.html
@@ -333,6 +333,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/index.html b/docs/signals_notebook/entities/index.html
index 3defe6ed..5c520801 100644
--- a/docs/signals_notebook/entities/index.html
+++ b/docs/signals_notebook/entities/index.html
@@ -44,7 +44,9 @@ <h1 class="title">Module <code>signals_notebook.entities</code></h1>
 from signals_notebook.entities.todo_list.todo_list import TodoList  # noqa
 from signals_notebook.entities.power_point import PowerPoint  # noqa
 from signals_notebook.entities.spotfire import Spotfire  # noqa
-from signals_notebook.entities.uploaded_resource import UploadedResource  # noqa</code></pre>
+from signals_notebook.entities.uploaded_resource import UploadedResource  # noqa
+from signals_notebook.entities.plates.plate_container import PlateContainer  # noqa
+from signals_notebook.entities.materials_table import MaterialsTable  # noqa</code></pre>
 </details>
 </section>
 <section>
@@ -86,10 +88,18 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt><code class="name"><a title="signals_notebook.entities.materials_table" href="materials_table.html">signals_notebook.entities.materials_table</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt><code class="name"><a title="signals_notebook.entities.notebook" href="notebook.html">signals_notebook.entities.notebook</a></code></dt>
 <dd>
 <div class="desc"></div>
 </dd>
+<dt><code class="name"><a title="signals_notebook.entities.plates" href="plates/index.html">signals_notebook.entities.plates</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
 <dt><code class="name"><a title="signals_notebook.entities.power_point" href="power_point.html">signals_notebook.entities.power_point</a></code></dt>
 <dd>
 <div class="desc"></div>
@@ -157,7 +167,9 @@ <h1>Index</h1>
 <li><code><a title="signals_notebook.entities.excel" href="excel.html">signals_notebook.entities.excel</a></code></li>
 <li><code><a title="signals_notebook.entities.experiment" href="experiment.html">signals_notebook.entities.experiment</a></code></li>
 <li><code><a title="signals_notebook.entities.image" href="image.html">signals_notebook.entities.image</a></code></li>
+<li><code><a title="signals_notebook.entities.materials_table" href="materials_table.html">signals_notebook.entities.materials_table</a></code></li>
 <li><code><a title="signals_notebook.entities.notebook" href="notebook.html">signals_notebook.entities.notebook</a></code></li>
+<li><code><a title="signals_notebook.entities.plates" href="plates/index.html">signals_notebook.entities.plates</a></code></li>
 <li><code><a title="signals_notebook.entities.power_point" href="power_point.html">signals_notebook.entities.power_point</a></code></li>
 <li><code><a title="signals_notebook.entities.samples" href="samples/index.html">signals_notebook.entities.samples</a></code></li>
 <li><code><a title="signals_notebook.entities.spotfire" href="spotfire.html">signals_notebook.entities.spotfire</a></code></li>
diff --git a/docs/signals_notebook/entities/materials_table.html b/docs/signals_notebook/entities/materials_table.html
new file mode 100644
index 00000000..84f43df0
--- /dev/null
+++ b/docs/signals_notebook/entities/materials_table.html
@@ -0,0 +1,167 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>signals_notebook.entities.materials_table API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>signals_notebook.entities.materials_table</code></h1>
+</header>
+<section id="section-intro">
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">import logging
+from typing import ClassVar, Literal
+
+from pydantic import Field
+
+from signals_notebook.common_types import EntityType, File
+from signals_notebook.entities.contentful_entity import ContentfulEntity
+
+log = logging.getLogger(__name__)
+
+
+class MaterialsTable(ContentfulEntity):
+    type: Literal[EntityType.MATERIAL_TABLE] = Field(allow_mutation=False)
+    _template_name: ClassVar = &#39;materials_table.html&#39;
+
+    @classmethod
+    def _get_entity_type(cls) -&gt; EntityType:
+        return EntityType.MATERIAL_TABLE
+
+    def get_content(self) -&gt; File:
+        return super()._get_content()</code></pre>
+</details>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="signals_notebook.entities.materials_table.MaterialsTable"><code class="flex name class">
+<span>class <span class="ident">MaterialsTable</span></span>
+<span>(</span><span>**data: Any)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class MaterialsTable(ContentfulEntity):
+    type: Literal[EntityType.MATERIAL_TABLE] = Field(allow_mutation=False)
+    _template_name: ClassVar = &#39;materials_table.html&#39;
+
+    @classmethod
+    def _get_entity_type(cls) -&gt; EntityType:
+        return EntityType.MATERIAL_TABLE
+
+    def get_content(self) -&gt; File:
+        return super()._get_content()</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></li>
+<li><a title="signals_notebook.entities.entity.Entity" href="entity.html#signals_notebook.entities.entity.Entity">Entity</a></li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>abc.ABC</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.materials_table.MaterialsTable.type"><code class="name">var <span class="ident">type</span> : Literal[<EntityType.MATERIAL_TABLE: 'materialsTable'>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="signals_notebook.entities.materials_table.MaterialsTable.get_content"><code class="name flex">
+<span>def <span class="ident">get_content</span></span>(<span>self) ‑> <a title="signals_notebook.common_types.File" href="../common_types.html#signals_notebook.common_types.File">File</a></span>
+</code></dt>
+<dd>
+<div class="desc"></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_content(self) -&gt; File:
+    return super()._get_content()</code></pre>
+</details>
+</dd>
+</dl>
+<h3>Inherited members</h3>
+<ul class="hlist">
+<li><code><b><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></b></code>:
+<ul class="hlist">
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_template_name" href="entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.load" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.load">load</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.refresh" href="entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.save" href="entity.html#signals_notebook.entities.entity.Entity.save">save</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.set_template_name" href="entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.short_description" href="entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
+</ul>
+</li>
+</ul>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="signals_notebook.entities" href="index.html">signals_notebook.entities</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="signals_notebook.entities.materials_table.MaterialsTable" href="#signals_notebook.entities.materials_table.MaterialsTable">MaterialsTable</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.materials_table.MaterialsTable.get_content" href="#signals_notebook.entities.materials_table.MaterialsTable.get_content">get_content</a></code></li>
+<li><code><a title="signals_notebook.entities.materials_table.MaterialsTable.type" href="#signals_notebook.entities.materials_table.MaterialsTable.type">type</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/signals_notebook/entities/notebook.html b/docs/signals_notebook/entities/notebook.html
index 6cb13f8e..72331293 100644
--- a/docs/signals_notebook/entities/notebook.html
+++ b/docs/signals_notebook/entities/notebook.html
@@ -367,6 +367,7 @@ <h3>Inherited members</h3>
 <ul class="hlist">
 <li><code><a title="signals_notebook.entities.container.Container.add_child" href="container.html#signals_notebook.entities.container.Container.add_child">add_child</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.container.Container.dump_templates" href="container.html#signals_notebook.entities.container.Container.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_children" href="container.html#signals_notebook.entities.container.Container.get_children">get_children</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_html" href="entity.html#signals_notebook.entities.entity.Entity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.container.Container.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
diff --git a/docs/signals_notebook/entities/plates/cell.html b/docs/signals_notebook/entities/plates/cell.html
new file mode 100644
index 00000000..31813179
--- /dev/null
+++ b/docs/signals_notebook/entities/plates/cell.html
@@ -0,0 +1,322 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>signals_notebook.entities.plates.cell API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>signals_notebook.entities.plates.cell</code></h1>
+</header>
+<section id="section-intro">
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">from enum import Enum
+from typing import Generic, List, Optional, TypeVar
+from uuid import UUID
+
+from pydantic import Field
+from pydantic.generics import GenericModel
+
+
+CellContentType = TypeVar(&#39;CellContentType&#39;)
+
+
+class ColumnDataType(str, Enum):
+    NUMBER = &#39;NUMBER&#39;
+    INTEGER = &#39;INTEGER&#39;
+    DATE_TIME = &#39;DATETIME&#39;
+    TEXT = &#39;TEXT&#39;
+    LIST = &#39;LIST&#39;
+    MULTI_SELECT = &#39;MULTI_SELECT&#39;
+    ATTRIBUTE_LIST = &#39;ATTRIBUTE_LIST&#39;
+    AUTOTEXT_LIST = &#39;AUTOTEXT_LIST&#39;
+    BOOLEAN = &#39;BOOLEAN&#39;
+    UNIT = &#39;UNIT&#39;
+    LINK = &#39;LINK&#39;
+    EXTERNAL_LINK = &#39;EXTERNAL_LINK&#39;
+
+
+class CellContent(GenericModel, Generic[CellContentType]):
+    user: Optional[str]
+    value: Optional[CellContentType] = None
+    values: Optional[List[CellContentType]] = None
+
+    class Config:
+        validate_assignment = True
+
+
+class PlateCell(GenericModel, Generic[CellContentType]):
+    id: UUID = Field(allow_mutation=False, alias=&#39;key&#39;)
+    type: ColumnDataType = Field(allow_mutation=False)
+    name: str = Field(allow_mutation=False)
+    content: CellContent[CellContentType]
+
+    class Config:
+        validate_assignment = True</code></pre>
+</details>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="signals_notebook.entities.plates.cell.CellContent"><code class="flex name class">
+<span>class <span class="ident">CellContent</span></span>
+<span>(</span><span>**data: Any)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class CellContent(GenericModel, Generic[CellContentType]):
+    user: Optional[str]
+    value: Optional[CellContentType] = None
+    values: Optional[List[CellContentType]] = None
+
+    class Config:
+        validate_assignment = True</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.cell.CellContent.Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.CellContent.user"><code class="name">var <span class="ident">user</span> : Optional[str]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.CellContent.value"><code class="name">var <span class="ident">value</span> : Optional[~CellContentType]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.CellContent.values"><code class="name">var <span class="ident">values</span> : Optional[List[~CellContentType]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType"><code class="flex name class">
+<span>class <span class="ident">ColumnDataType</span></span>
+<span>(</span><span>value, names=None, *, module=None, qualname=None, type=None, start=1)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>An enumeration.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class ColumnDataType(str, Enum):
+    NUMBER = &#39;NUMBER&#39;
+    INTEGER = &#39;INTEGER&#39;
+    DATE_TIME = &#39;DATETIME&#39;
+    TEXT = &#39;TEXT&#39;
+    LIST = &#39;LIST&#39;
+    MULTI_SELECT = &#39;MULTI_SELECT&#39;
+    ATTRIBUTE_LIST = &#39;ATTRIBUTE_LIST&#39;
+    AUTOTEXT_LIST = &#39;AUTOTEXT_LIST&#39;
+    BOOLEAN = &#39;BOOLEAN&#39;
+    UNIT = &#39;UNIT&#39;
+    LINK = &#39;LINK&#39;
+    EXTERNAL_LINK = &#39;EXTERNAL_LINK&#39;</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>builtins.str</li>
+<li>enum.Enum</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.ATTRIBUTE_LIST"><code class="name">var <span class="ident">ATTRIBUTE_LIST</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.AUTOTEXT_LIST"><code class="name">var <span class="ident">AUTOTEXT_LIST</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.BOOLEAN"><code class="name">var <span class="ident">BOOLEAN</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.DATE_TIME"><code class="name">var <span class="ident">DATE_TIME</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.EXTERNAL_LINK"><code class="name">var <span class="ident">EXTERNAL_LINK</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.INTEGER"><code class="name">var <span class="ident">INTEGER</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.LINK"><code class="name">var <span class="ident">LINK</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.LIST"><code class="name">var <span class="ident">LIST</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.MULTI_SELECT"><code class="name">var <span class="ident">MULTI_SELECT</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.NUMBER"><code class="name">var <span class="ident">NUMBER</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.TEXT"><code class="name">var <span class="ident">TEXT</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.ColumnDataType.UNIT"><code class="name">var <span class="ident">UNIT</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.PlateCell"><code class="flex name class">
+<span>class <span class="ident">PlateCell</span></span>
+<span>(</span><span>**data: Any)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class PlateCell(GenericModel, Generic[CellContentType]):
+    id: UUID = Field(allow_mutation=False, alias=&#39;key&#39;)
+    type: ColumnDataType = Field(allow_mutation=False)
+    name: str = Field(allow_mutation=False)
+    content: CellContent[CellContentType]
+
+    class Config:
+        validate_assignment = True</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.cell.PlateCell.Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.PlateCell.content"><code class="name">var <span class="ident">content</span> : <a title="signals_notebook.entities.plates.cell.CellContent" href="#signals_notebook.entities.plates.cell.CellContent">CellContent</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.PlateCell.id"><code class="name">var <span class="ident">id</span> : uuid.UUID</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.PlateCell.name"><code class="name">var <span class="ident">name</span> : str</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.cell.PlateCell.type"><code class="name">var <span class="ident">type</span> : <a title="signals_notebook.entities.plates.cell.ColumnDataType" href="#signals_notebook.entities.plates.cell.ColumnDataType">ColumnDataType</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="signals_notebook.entities.plates" href="index.html">signals_notebook.entities.plates</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.cell.CellContent" href="#signals_notebook.entities.plates.cell.CellContent">CellContent</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.cell.CellContent.Config" href="#signals_notebook.entities.plates.cell.CellContent.Config">Config</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.CellContent.user" href="#signals_notebook.entities.plates.cell.CellContent.user">user</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.CellContent.value" href="#signals_notebook.entities.plates.cell.CellContent.value">value</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.CellContent.values" href="#signals_notebook.entities.plates.cell.CellContent.values">values</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.cell.ColumnDataType" href="#signals_notebook.entities.plates.cell.ColumnDataType">ColumnDataType</a></code></h4>
+<ul class="two-column">
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.ATTRIBUTE_LIST" href="#signals_notebook.entities.plates.cell.ColumnDataType.ATTRIBUTE_LIST">ATTRIBUTE_LIST</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.AUTOTEXT_LIST" href="#signals_notebook.entities.plates.cell.ColumnDataType.AUTOTEXT_LIST">AUTOTEXT_LIST</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.BOOLEAN" href="#signals_notebook.entities.plates.cell.ColumnDataType.BOOLEAN">BOOLEAN</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.DATE_TIME" href="#signals_notebook.entities.plates.cell.ColumnDataType.DATE_TIME">DATE_TIME</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.EXTERNAL_LINK" href="#signals_notebook.entities.plates.cell.ColumnDataType.EXTERNAL_LINK">EXTERNAL_LINK</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.INTEGER" href="#signals_notebook.entities.plates.cell.ColumnDataType.INTEGER">INTEGER</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.LINK" href="#signals_notebook.entities.plates.cell.ColumnDataType.LINK">LINK</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.LIST" href="#signals_notebook.entities.plates.cell.ColumnDataType.LIST">LIST</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.MULTI_SELECT" href="#signals_notebook.entities.plates.cell.ColumnDataType.MULTI_SELECT">MULTI_SELECT</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.NUMBER" href="#signals_notebook.entities.plates.cell.ColumnDataType.NUMBER">NUMBER</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.TEXT" href="#signals_notebook.entities.plates.cell.ColumnDataType.TEXT">TEXT</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.ColumnDataType.UNIT" href="#signals_notebook.entities.plates.cell.ColumnDataType.UNIT">UNIT</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.cell.PlateCell" href="#signals_notebook.entities.plates.cell.PlateCell">PlateCell</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.cell.PlateCell.Config" href="#signals_notebook.entities.plates.cell.PlateCell.Config">Config</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.PlateCell.content" href="#signals_notebook.entities.plates.cell.PlateCell.content">content</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.PlateCell.id" href="#signals_notebook.entities.plates.cell.PlateCell.id">id</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.PlateCell.name" href="#signals_notebook.entities.plates.cell.PlateCell.name">name</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.cell.PlateCell.type" href="#signals_notebook.entities.plates.cell.PlateCell.type">type</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/signals_notebook/entities/plates/index.html b/docs/signals_notebook/entities/plates/index.html
new file mode 100644
index 00000000..f6030566
--- /dev/null
+++ b/docs/signals_notebook/entities/plates/index.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>signals_notebook.entities.plates API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>signals_notebook.entities.plates</code></h1>
+</header>
+<section id="section-intro">
+</section>
+<section>
+<h2 class="section-title" id="header-submodules">Sub-modules</h2>
+<dl>
+<dt><code class="name"><a title="signals_notebook.entities.plates.cell" href="cell.html">signals_notebook.entities.plates.cell</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="signals_notebook.entities.plates.plate_container" href="plate_container.html">signals_notebook.entities.plates.plate_container</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt><code class="name"><a title="signals_notebook.entities.plates.plate_row" href="plate_row.html">signals_notebook.entities.plates.plate_row</a></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="signals_notebook.entities" href="../index.html">signals_notebook.entities</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-submodules">Sub-modules</a></h3>
+<ul>
+<li><code><a title="signals_notebook.entities.plates.cell" href="cell.html">signals_notebook.entities.plates.cell</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container" href="plate_container.html">signals_notebook.entities.plates.plate_container</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_row" href="plate_row.html">signals_notebook.entities.plates.plate_row</a></code></li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/signals_notebook/entities/plates/plate_container.html b/docs/signals_notebook/entities/plates/plate_container.html
new file mode 100644
index 00000000..f548c940
--- /dev/null
+++ b/docs/signals_notebook/entities/plates/plate_container.html
@@ -0,0 +1,424 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>signals_notebook.entities.plates.plate_container API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>signals_notebook.entities.plates.plate_container</code></h1>
+</header>
+<section id="section-intro">
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">import logging
+from typing import cast, ClassVar, Dict, List, Literal, Union
+from uuid import UUID
+
+from pydantic import Field, PrivateAttr
+
+from signals_notebook.api import SignalsNotebookApi
+from signals_notebook.common_types import EntityType, File, Response, ResponseData
+from signals_notebook.entities.contentful_entity import ContentfulEntity
+from signals_notebook.entities.plates.plate_row import PlateRow
+from signals_notebook.jinja_env import env
+
+log = logging.getLogger(__name__)
+
+
+class PlateContainerDataResponse(Response[PlateRow]):
+    pass
+
+
+class PlateContainer(ContentfulEntity):
+    type: Literal[EntityType.PLATE_CONTAINER] = Field(allow_mutation=False)
+    _rows: List[PlateRow] = PrivateAttr(default=[])
+    _rows_by_id: Dict[UUID, PlateRow] = PrivateAttr(default={})
+    _template_name: ClassVar = &#39;plate_container.html&#39;
+
+    def __getitem__(self, index: Union[int, str, UUID]) -&gt; PlateRow:
+        if not self._rows:
+            self._reload_data()
+
+        if isinstance(index, int):
+            return self._rows[index]
+
+        if isinstance(index, str):
+            return self._rows_by_id[UUID(index)]
+
+        if isinstance(index, UUID):
+            return self._rows_by_id[index]
+
+        raise IndexError(&#39;Invalid index&#39;)
+
+    def __iter__(self):
+        if not self._rows:
+            self._reload_data()
+
+        return self._rows.__iter__()
+
+    @classmethod
+    def _get_entity_type(cls) -&gt; EntityType:
+        return EntityType.PLATE_CONTAINER
+
+    def _reload_data(self):
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Reloading rows for Plate Container: %s...&#39;, self.eid)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(&#39;plates&#39;, self.eid, &#39;summary&#39;),
+        )
+        result = PlateContainerDataResponse(**response.json())
+        self._rows = []
+        self._rows_by_id = {}
+        for item in result.data:
+            row = cast(PlateRow, cast(ResponseData, item).body)
+            assert row.id
+
+            self._rows.append(row)
+            self._rows_by_id[row.id] = row
+        log.debug(&#39;Data in Plate Container: %s were reloaded&#39;, self.eid)
+
+    def get_content(self) -&gt; File:
+        &#34;&#34;&#34;Get PlateContainer content
+
+        Returns:
+            File
+        &#34;&#34;&#34;
+        return super()._get_content()
+
+    def get_html(self) -&gt; str:
+        &#34;&#34;&#34;Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        &#34;&#34;&#34;
+        if not self._rows:
+            self._reload_data()
+        table_head = None
+        if self._rows:
+            table_head = self._rows[0]
+
+        template = env.get_template(self._template_name)
+        log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
+        return template.render(name=self.name, table_head=table_head, rows=self._rows)</code></pre>
+</details>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainer"><code class="flex name class">
+<span>class <span class="ident">PlateContainer</span></span>
+<span>(</span><span>**data: Any)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class PlateContainer(ContentfulEntity):
+    type: Literal[EntityType.PLATE_CONTAINER] = Field(allow_mutation=False)
+    _rows: List[PlateRow] = PrivateAttr(default=[])
+    _rows_by_id: Dict[UUID, PlateRow] = PrivateAttr(default={})
+    _template_name: ClassVar = &#39;plate_container.html&#39;
+
+    def __getitem__(self, index: Union[int, str, UUID]) -&gt; PlateRow:
+        if not self._rows:
+            self._reload_data()
+
+        if isinstance(index, int):
+            return self._rows[index]
+
+        if isinstance(index, str):
+            return self._rows_by_id[UUID(index)]
+
+        if isinstance(index, UUID):
+            return self._rows_by_id[index]
+
+        raise IndexError(&#39;Invalid index&#39;)
+
+    def __iter__(self):
+        if not self._rows:
+            self._reload_data()
+
+        return self._rows.__iter__()
+
+    @classmethod
+    def _get_entity_type(cls) -&gt; EntityType:
+        return EntityType.PLATE_CONTAINER
+
+    def _reload_data(self):
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Reloading rows for Plate Container: %s...&#39;, self.eid)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(&#39;plates&#39;, self.eid, &#39;summary&#39;),
+        )
+        result = PlateContainerDataResponse(**response.json())
+        self._rows = []
+        self._rows_by_id = {}
+        for item in result.data:
+            row = cast(PlateRow, cast(ResponseData, item).body)
+            assert row.id
+
+            self._rows.append(row)
+            self._rows_by_id[row.id] = row
+        log.debug(&#39;Data in Plate Container: %s were reloaded&#39;, self.eid)
+
+    def get_content(self) -&gt; File:
+        &#34;&#34;&#34;Get PlateContainer content
+
+        Returns:
+            File
+        &#34;&#34;&#34;
+        return super()._get_content()
+
+    def get_html(self) -&gt; str:
+        &#34;&#34;&#34;Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        &#34;&#34;&#34;
+        if not self._rows:
+            self._reload_data()
+        table_head = None
+        if self._rows:
+            table_head = self._rows[0]
+
+        template = env.get_template(self._template_name)
+        log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
+        return template.render(name=self.name, table_head=table_head, rows=self._rows)</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></li>
+<li><a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>abc.ABC</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainer.type"><code class="name">var <span class="ident">type</span> : Literal[<EntityType.PLATE_CONTAINER: 'plateContainer'>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+<h3>Methods</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainer.get_content"><code class="name flex">
+<span>def <span class="ident">get_content</span></span>(<span>self) ‑> <a title="signals_notebook.common_types.File" href="../../common_types.html#signals_notebook.common_types.File">File</a></span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get PlateContainer content</p>
+<h2 id="returns">Returns</h2>
+<p>File</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_content(self) -&gt; File:
+    &#34;&#34;&#34;Get PlateContainer content
+
+    Returns:
+        File
+    &#34;&#34;&#34;
+    return super()._get_content()</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainer.get_html"><code class="name flex">
+<span>def <span class="ident">get_html</span></span>(<span>self) ‑> str</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get in HTML format</p>
+<h2 id="returns">Returns</h2>
+<p>Rendered HTML in string format</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_html(self) -&gt; str:
+    &#34;&#34;&#34;Get in HTML format
+
+    Returns:
+        Rendered HTML in string format
+    &#34;&#34;&#34;
+    if not self._rows:
+        self._reload_data()
+    table_head = None
+    if self._rows:
+        table_head = self._rows[0]
+
+    template = env.get_template(self._template_name)
+    log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
+    return template.render(name=self.name, table_head=table_head, rows=self._rows)</code></pre>
+</details>
+</dd>
+</dl>
+<h3>Inherited members</h3>
+<ul class="hlist">
+<li><code><b><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></b></code>:
+<ul class="hlist">
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="../entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.load" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.load">load</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.refresh" href="../entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.save" href="../entity.html#signals_notebook.entities.entity.Entity.save">save</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.set_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.short_description" href="../entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
+</ul>
+</li>
+</ul>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse"><code class="flex name class">
+<span>class <span class="ident">PlateContainerDataResponse</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class PlateContainerDataResponse(Response[PlateRow]):
+    pass</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow]" href="#signals_notebook.entities.plates.plate_container.Response[PlateRow]">Response[PlateRow]</a></li>
+<li><a title="signals_notebook.common_types.Response" href="../../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[PlateRow], List[pydantic.generics.ResponseData[PlateRow]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.Response[PlateRow]"><code class="flex name class">
+<span>class <span class="ident">Response[PlateRow]</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.common_types.Response" href="../../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Subclasses</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse" href="#signals_notebook.entities.plates.plate_container.PlateContainerDataResponse">PlateContainerDataResponse</a></li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_container.Response[PlateRow].Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.Response[PlateRow].data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[PlateRow], List[pydantic.generics.ResponseData[PlateRow]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_container.Response[PlateRow].links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="signals_notebook.entities.plates" href="index.html">signals_notebook.entities.plates</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.plate_container.PlateContainer" href="#signals_notebook.entities.plates.plate_container.PlateContainer">PlateContainer</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.plate_container.PlateContainer.get_content" href="#signals_notebook.entities.plates.plate_container.PlateContainer.get_content">get_content</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container.PlateContainer.get_html" href="#signals_notebook.entities.plates.plate_container.PlateContainer.get_html">get_html</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container.PlateContainer.type" href="#signals_notebook.entities.plates.plate_container.PlateContainer.type">type</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse" href="#signals_notebook.entities.plates.plate_container.PlateContainerDataResponse">PlateContainerDataResponse</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.data" href="#signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.data">data</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.links" href="#signals_notebook.entities.plates.plate_container.PlateContainerDataResponse.links">links</a></code></li>
+</ul>
+</li>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow]" href="#signals_notebook.entities.plates.plate_container.Response[PlateRow]">Response[PlateRow]</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow].Config" href="#signals_notebook.entities.plates.plate_container.Response[PlateRow].Config">Config</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow].data" href="#signals_notebook.entities.plates.plate_container.Response[PlateRow].data">data</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_container.Response[PlateRow].links" href="#signals_notebook.entities.plates.plate_container.Response[PlateRow].links">links</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/signals_notebook/entities/plates/plate_row.html b/docs/signals_notebook/entities/plates/plate_row.html
new file mode 100644
index 00000000..6ecd4bd5
--- /dev/null
+++ b/docs/signals_notebook/entities/plates/plate_row.html
@@ -0,0 +1,197 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
+<meta name="generator" content="pdoc 0.10.0" />
+<title>signals_notebook.entities.plates.plate_row API documentation</title>
+<meta name="description" content="" />
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
+<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
+<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
+<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
+<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
+<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
+<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
+<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
+</head>
+<body>
+<main>
+<article id="content">
+<header>
+<h1 class="title">Module <code>signals_notebook.entities.plates.plate_row</code></h1>
+</header>
+<section id="section-intro">
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">import logging
+from typing import Dict, List, Literal, Optional, Union
+from uuid import UUID
+
+from pydantic import BaseModel, Field, PrivateAttr
+
+from signals_notebook.common_types import ObjectType
+from signals_notebook.entities.plates.cell import PlateCell
+
+log = logging.getLogger(__name__)
+
+
+class PlateRow(BaseModel):
+    id: Optional[UUID] = Field(allow_mutation=False, default=None)
+    type: Literal[ObjectType.PLATE_ROW] = Field(allow_mutation=False, default=ObjectType.ADT_ROW)
+    cells: List[PlateCell]
+    _cells_dict: Dict[Union[UUID, str], PlateCell] = PrivateAttr(default={})
+
+    def __init__(self, **data):
+        super().__init__(**data)
+
+        for cell in self.cells:
+            self._cells_dict[cell.id] = cell
+            self._cells_dict[cell.name] = cell
+
+    class Config:
+        validate_assignment = True
+
+    def __getitem__(self, index: Union[int, str, UUID]) -&gt; PlateCell:
+        if isinstance(index, int):
+            return self.cells[index]
+
+        if isinstance(index, str):
+            if index in self._cells_dict:
+                return self._cells_dict[index]
+
+            try:
+                if UUID(index) in self._cells_dict:
+                    return self._cells_dict[UUID(index)]
+            except ValueError:
+                pass
+
+        if isinstance(index, UUID):
+            return self._cells_dict[index]
+
+        raise IndexError(&#39;Invalid index&#39;)
+
+    def __iter__(self):
+        return self.cells.__iter__()</code></pre>
+</details>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+</section>
+<section>
+<h2 class="section-title" id="header-classes">Classes</h2>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_row.PlateRow"><code class="flex name class">
+<span>class <span class="ident">PlateRow</span></span>
+<span>(</span><span>**data)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class PlateRow(BaseModel):
+    id: Optional[UUID] = Field(allow_mutation=False, default=None)
+    type: Literal[ObjectType.PLATE_ROW] = Field(allow_mutation=False, default=ObjectType.ADT_ROW)
+    cells: List[PlateCell]
+    _cells_dict: Dict[Union[UUID, str], PlateCell] = PrivateAttr(default={})
+
+    def __init__(self, **data):
+        super().__init__(**data)
+
+        for cell in self.cells:
+            self._cells_dict[cell.id] = cell
+            self._cells_dict[cell.name] = cell
+
+    class Config:
+        validate_assignment = True
+
+    def __getitem__(self, index: Union[int, str, UUID]) -&gt; PlateCell:
+        if isinstance(index, int):
+            return self.cells[index]
+
+        if isinstance(index, str):
+            if index in self._cells_dict:
+                return self._cells_dict[index]
+
+            try:
+                if UUID(index) in self._cells_dict:
+                    return self._cells_dict[UUID(index)]
+            except ValueError:
+                pass
+
+        if isinstance(index, UUID):
+            return self._cells_dict[index]
+
+        raise IndexError(&#39;Invalid index&#39;)
+
+    def __iter__(self):
+        return self.cells.__iter__()</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.plates.plate_row.PlateRow.Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_row.PlateRow.cells"><code class="name">var <span class="ident">cells</span> : List[<a title="signals_notebook.entities.plates.cell.PlateCell" href="cell.html#signals_notebook.entities.plates.cell.PlateCell">PlateCell</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_row.PlateRow.id"><code class="name">var <span class="ident">id</span> : Optional[uuid.UUID]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.plates.plate_row.PlateRow.type"><code class="name">var <span class="ident">type</span> : Literal[<ObjectType.PLATE_ROW: 'plateRow'>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
+</dl>
+</section>
+</article>
+<nav id="sidebar">
+<h1>Index</h1>
+<div class="toc">
+<ul></ul>
+</div>
+<ul id="index">
+<li><h3>Super-module</h3>
+<ul>
+<li><code><a title="signals_notebook.entities.plates" href="index.html">signals_notebook.entities.plates</a></code></li>
+</ul>
+</li>
+<li><h3><a href="#header-classes">Classes</a></h3>
+<ul>
+<li>
+<h4><code><a title="signals_notebook.entities.plates.plate_row.PlateRow" href="#signals_notebook.entities.plates.plate_row.PlateRow">PlateRow</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.plates.plate_row.PlateRow.Config" href="#signals_notebook.entities.plates.plate_row.PlateRow.Config">Config</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_row.PlateRow.cells" href="#signals_notebook.entities.plates.plate_row.PlateRow.cells">cells</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_row.PlateRow.id" href="#signals_notebook.entities.plates.plate_row.PlateRow.id">id</a></code></li>
+<li><code><a title="signals_notebook.entities.plates.plate_row.PlateRow.type" href="#signals_notebook.entities.plates.plate_row.PlateRow.type">type</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</nav>
+</main>
+<footer id="footer">
+<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
+</footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/signals_notebook/entities/power_point.html b/docs/signals_notebook/entities/power_point.html
index 0ca974a7..2fd7ea57 100644
--- a/docs/signals_notebook/entities/power_point.html
+++ b/docs/signals_notebook/entities/power_point.html
@@ -277,6 +277,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/samples/cell.html b/docs/signals_notebook/entities/samples/cell.html
index 7e8e6c35..ae4acb29 100644
--- a/docs/signals_notebook/entities/samples/cell.html
+++ b/docs/signals_notebook/entities/samples/cell.html
@@ -45,19 +45,48 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.cell</code></h1
     _changed: bool = PrivateAttr(default=False)
 
     def set_value(self, new_value: CellValueType) -&gt; None:
+        &#34;&#34;&#34;Set new value
+
+        Args:
+            new_value: new value for value field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.value = new_value
         self._changed = True
 
     def set_values(self, new_values: List[CellValueType]) -&gt; None:
+        &#34;&#34;&#34;Set new values
+
+        Args:
+            new_values: new list of values for values field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.values = new_values
         self._changed = True
 
     def set_name(self, new_name: str) -&gt; None:
+        &#34;&#34;&#34;Set new name
+
+        Args:
+            new_name: new name for name field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.name = new_name
         self._changed = True
 
     @property
     def is_changed(self) -&gt; bool:
+        &#34;&#34;&#34;Get is_changed value
+
+        Returns:
+            bool: True/False
+        &#34;&#34;&#34;
         return self._changed
 
 
@@ -77,32 +106,81 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.cell</code></h1
     content: SampleCellContent = Field(default=SampleCellContent())
 
     def set_content_value(self, new_value: CellValueType) -&gt; None:
+        &#34;&#34;&#34;Set new content value
+
+        Args:
+            new_value: new value of SampleCellContent value field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_value(new_value)
 
     def set_content_values(self, new_values: List[CellValueType]) -&gt; None:
+        &#34;&#34;&#34;Set new content values
+
+        Args:
+            new_values: new list of values of SampleCellContent values field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_values(new_values)
 
     def set_content_name(self, new_name: str) -&gt; None:
+        &#34;&#34;&#34;Set new content name
+
+        Args:
+            new_name: new name of SampleCellContent name field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_name(new_name)
 
     @property
     def content_value(self) -&gt; Optional[CellValueType]:
+        &#34;&#34;&#34;Get content value
+
+        Returns:
+            Optional[CellValueType]
+        &#34;&#34;&#34;
         return self.content.value
 
     @property
     def content_values(self) -&gt; Optional[List[CellValueType]]:
+        &#34;&#34;&#34;Get content values
+
+        Returns:
+            Optional[List[CellValueType]]
+        &#34;&#34;&#34;
         return self.content.values
 
     @property
     def content_name(self) -&gt; Optional[str]:
+        &#34;&#34;&#34;Get content name
+
+        Returns:
+            Optional[str]
+        &#34;&#34;&#34;
         return self.content.name
 
     @property
     def is_changed(self) -&gt; bool:
+        &#34;&#34;&#34;Checking if SampleCell has been modified
+
+        Returns:
+            bool
+        &#34;&#34;&#34;
         return False if self.content is None else self.content.is_changed
 
     @property
     def representation_for_update(self) -&gt; SampleCellBody:
+        &#34;&#34;&#34;Get representation of body for update
+
+        Returns:
+            SampleCellBody
+        &#34;&#34;&#34;
         return SampleCellBody(id=str(self.id), attributes=Content(content=self.content))</code></pre>
 </details>
 </section>
@@ -159,32 +237,81 @@ <h3>Class variables</h3>
     content: SampleCellContent = Field(default=SampleCellContent())
 
     def set_content_value(self, new_value: CellValueType) -&gt; None:
+        &#34;&#34;&#34;Set new content value
+
+        Args:
+            new_value: new value of SampleCellContent value field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_value(new_value)
 
     def set_content_values(self, new_values: List[CellValueType]) -&gt; None:
+        &#34;&#34;&#34;Set new content values
+
+        Args:
+            new_values: new list of values of SampleCellContent values field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_values(new_values)
 
     def set_content_name(self, new_name: str) -&gt; None:
+        &#34;&#34;&#34;Set new content name
+
+        Args:
+            new_name: new name of SampleCellContent name field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.content.set_name(new_name)
 
     @property
     def content_value(self) -&gt; Optional[CellValueType]:
+        &#34;&#34;&#34;Get content value
+
+        Returns:
+            Optional[CellValueType]
+        &#34;&#34;&#34;
         return self.content.value
 
     @property
     def content_values(self) -&gt; Optional[List[CellValueType]]:
+        &#34;&#34;&#34;Get content values
+
+        Returns:
+            Optional[List[CellValueType]]
+        &#34;&#34;&#34;
         return self.content.values
 
     @property
     def content_name(self) -&gt; Optional[str]:
+        &#34;&#34;&#34;Get content name
+
+        Returns:
+            Optional[str]
+        &#34;&#34;&#34;
         return self.content.name
 
     @property
     def is_changed(self) -&gt; bool:
+        &#34;&#34;&#34;Checking if SampleCell has been modified
+
+        Returns:
+            bool
+        &#34;&#34;&#34;
         return False if self.content is None else self.content.is_changed
 
     @property
     def representation_for_update(self) -&gt; SampleCellBody:
+        &#34;&#34;&#34;Get representation of body for update
+
+        Returns:
+            SampleCellBody
+        &#34;&#34;&#34;
         return SampleCellBody(id=str(self.id), attributes=Content(content=self.content))</code></pre>
 </details>
 <h3>Ancestors</h3>
@@ -211,61 +338,96 @@ <h3>Instance variables</h3>
 <dl>
 <dt id="signals_notebook.entities.samples.cell.SampleCell.content_name"><code class="name">var <span class="ident">content_name</span> : Optional[str]</code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get content name</p>
+<h2 id="returns">Returns</h2>
+<p>Optional[str]</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def content_name(self) -&gt; Optional[str]:
+    &#34;&#34;&#34;Get content name
+
+    Returns:
+        Optional[str]
+    &#34;&#34;&#34;
     return self.content.name</code></pre>
 </details>
 </dd>
 <dt id="signals_notebook.entities.samples.cell.SampleCell.content_value"><code class="name">var <span class="ident">content_value</span> : Optional[~CellValueType]</code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get content value</p>
+<h2 id="returns">Returns</h2>
+<p>Optional[CellValueType]</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def content_value(self) -&gt; Optional[CellValueType]:
+    &#34;&#34;&#34;Get content value
+
+    Returns:
+        Optional[CellValueType]
+    &#34;&#34;&#34;
     return self.content.value</code></pre>
 </details>
 </dd>
 <dt id="signals_notebook.entities.samples.cell.SampleCell.content_values"><code class="name">var <span class="ident">content_values</span> : Optional[List[~CellValueType]]</code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get content values</p>
+<h2 id="returns">Returns</h2>
+<p>Optional[List[CellValueType]]</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def content_values(self) -&gt; Optional[List[CellValueType]]:
+    &#34;&#34;&#34;Get content values
+
+    Returns:
+        Optional[List[CellValueType]]
+    &#34;&#34;&#34;
     return self.content.values</code></pre>
 </details>
 </dd>
 <dt id="signals_notebook.entities.samples.cell.SampleCell.is_changed"><code class="name">var <span class="ident">is_changed</span> : bool</code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Checking if SampleCell has been modified</p>
+<h2 id="returns">Returns</h2>
+<p>bool</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def is_changed(self) -&gt; bool:
+    &#34;&#34;&#34;Checking if SampleCell has been modified
+
+    Returns:
+        bool
+    &#34;&#34;&#34;
     return False if self.content is None else self.content.is_changed</code></pre>
 </details>
 </dd>
 <dt id="signals_notebook.entities.samples.cell.SampleCell.representation_for_update"><code class="name">var <span class="ident">representation_for_update</span> : <a title="signals_notebook.entities.samples.cell.SampleCellBody" href="#signals_notebook.entities.samples.cell.SampleCellBody">SampleCellBody</a></code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get representation of body for update</p>
+<h2 id="returns">Returns</h2>
+<p>SampleCellBody</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def representation_for_update(self) -&gt; SampleCellBody:
+    &#34;&#34;&#34;Get representation of body for update
+
+    Returns:
+        SampleCellBody
+    &#34;&#34;&#34;
     return SampleCellBody(id=str(self.id), attributes=Content(content=self.content))</code></pre>
 </details>
 </dd>
@@ -276,12 +438,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_content_name</span></span>(<span>self, new_name: str) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new content name</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_name</code></strong></dt>
+<dd>new name of SampleCellContent name field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_content_name(self, new_name: str) -&gt; None:
+    &#34;&#34;&#34;Set new content name
+
+    Args:
+        new_name: new name of SampleCellContent name field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.content.set_name(new_name)</code></pre>
 </details>
 </dd>
@@ -289,12 +465,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_content_value</span></span>(<span>self, new_value: ~CellValueType) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new content value</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_value</code></strong></dt>
+<dd>new value of SampleCellContent value field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_content_value(self, new_value: CellValueType) -&gt; None:
+    &#34;&#34;&#34;Set new content value
+
+    Args:
+        new_value: new value of SampleCellContent value field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.content.set_value(new_value)</code></pre>
 </details>
 </dd>
@@ -302,12 +492,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_content_values</span></span>(<span>self, new_values: List[~CellValueType]) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new content values</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_values</code></strong></dt>
+<dd>new list of values of SampleCellContent values field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_content_values(self, new_values: List[CellValueType]) -&gt; None:
+    &#34;&#34;&#34;Set new content values
+
+    Args:
+        new_values: new list of values of SampleCellContent values field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.content.set_values(new_values)</code></pre>
 </details>
 </dd>
@@ -369,19 +573,48 @@ <h3>Class variables</h3>
     _changed: bool = PrivateAttr(default=False)
 
     def set_value(self, new_value: CellValueType) -&gt; None:
+        &#34;&#34;&#34;Set new value
+
+        Args:
+            new_value: new value for value field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.value = new_value
         self._changed = True
 
     def set_values(self, new_values: List[CellValueType]) -&gt; None:
+        &#34;&#34;&#34;Set new values
+
+        Args:
+            new_values: new list of values for values field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.values = new_values
         self._changed = True
 
     def set_name(self, new_name: str) -&gt; None:
+        &#34;&#34;&#34;Set new name
+
+        Args:
+            new_name: new name for name field
+
+        Returns:
+
+        &#34;&#34;&#34;
         self.name = new_name
         self._changed = True
 
     @property
     def is_changed(self) -&gt; bool:
+        &#34;&#34;&#34;Get is_changed value
+
+        Returns:
+            bool: True/False
+        &#34;&#34;&#34;
         return self._changed</code></pre>
 </details>
 <h3>Ancestors</h3>
@@ -414,13 +647,23 @@ <h3>Instance variables</h3>
 <dl>
 <dt id="signals_notebook.entities.samples.cell.SampleCellContent.is_changed"><code class="name">var <span class="ident">is_changed</span> : bool</code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get is_changed value</p>
+<h2 id="returns">Returns</h2>
+<dl>
+<dt><code>bool</code></dt>
+<dd>True/False</dd>
+</dl></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">@property
 def is_changed(self) -&gt; bool:
+    &#34;&#34;&#34;Get is_changed value
+
+    Returns:
+        bool: True/False
+    &#34;&#34;&#34;
     return self._changed</code></pre>
 </details>
 </dd>
@@ -431,12 +674,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_name</span></span>(<span>self, new_name: str) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new name</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_name</code></strong></dt>
+<dd>new name for name field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_name(self, new_name: str) -&gt; None:
+    &#34;&#34;&#34;Set new name
+
+    Args:
+        new_name: new name for name field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.name = new_name
     self._changed = True</code></pre>
 </details>
@@ -445,12 +702,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_value</span></span>(<span>self, new_value: ~CellValueType) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new value</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_value</code></strong></dt>
+<dd>new value for value field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_value(self, new_value: CellValueType) -&gt; None:
+    &#34;&#34;&#34;Set new value
+
+    Args:
+        new_value: new value for value field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.value = new_value
     self._changed = True</code></pre>
 </details>
@@ -459,12 +730,26 @@ <h3>Methods</h3>
 <span>def <span class="ident">set_values</span></span>(<span>self, new_values: List[~CellValueType]) ‑> None</span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Set new values</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>new_values</code></strong></dt>
+<dd>new list of values for values field</dd>
+</dl>
+<p>Returns:</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def set_values(self, new_values: List[CellValueType]) -&gt; None:
+    &#34;&#34;&#34;Set new values
+
+    Args:
+        new_values: new list of values for values field
+
+    Returns:
+
+    &#34;&#34;&#34;
     self.values = new_values
     self._changed = True</code></pre>
 </details>
diff --git a/docs/signals_notebook/entities/samples/sample.html b/docs/signals_notebook/entities/samples/sample.html
index 09e783d2..2cfc533f 100644
--- a/docs/signals_notebook/entities/samples/sample.html
+++ b/docs/signals_notebook/entities/samples/sample.html
@@ -27,6 +27,7 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">import json
+import logging
 from typing import cast, Dict, List, Literal, Optional, TYPE_CHECKING, Union
 from uuid import UUID
 
@@ -48,6 +49,8 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
 if TYPE_CHECKING:
     from signals_notebook.entities import SamplesContainer
 
+log = logging.getLogger(__name__)
+
 
 class _SampleAttributes(BaseModel):
     fields: Optional[List[SampleCell]] = []
@@ -109,6 +112,7 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
         return &#39;samples&#39;
 
     def _reload_cells(self) -&gt; None:
+        log.debug(&#39;Reloading cells for Sample: %s...&#39;, self.eid)
         self._cells = []
         self._cells_by_id = {}
 
@@ -129,8 +133,18 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
 
             self._cells.append(sample_cell)
             self._cells_by_id[sample_cell.id] = sample_cell
+        log.debug(&#39;Cells for Sample: %s were reloaded&#39;, self.eid)
 
     def save(self, force: bool = True) -&gt; None:
+        &#34;&#34;&#34;Save Sample.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Saving Sample: %s...&#39;, self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         request_body = []
@@ -153,6 +167,7 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
             },
         )
         self._reload_cells()
+        log.debug(&#39;Sample: %s were saved successfully.&#39;, self.eid)
 
     @classmethod
     def create(
@@ -164,6 +179,22 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.sample</code></
         digest: str = None,
         force: bool = True,
     ) -&gt; &#39;Sample&#39;:
+        &#34;&#34;&#34;Create Sample Entity
+
+        Args:
+            cells: Sample&#39;s data
+            template: template for Sample creation
+            ancestors: Container or SamplesContainer where create new Sample
+            digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+                If the parameter &#39;force&#39; is true, this parameter is optional.
+                If the parameter &#39;force&#39; is false, this parameter is required.
+            force: Force to create without doing digest check
+
+        Returns:
+            Sample
+        &#34;&#34;&#34;
+        log.debug(&#39;Create Sample: %s &#39;, cls.__name__)
+
         relationships = None
         if template or ancestors:
             relationships = _SampleRelationships(
@@ -311,6 +342,7 @@ <h3>Class variables</h3>
         return &#39;samples&#39;
 
     def _reload_cells(self) -&gt; None:
+        log.debug(&#39;Reloading cells for Sample: %s...&#39;, self.eid)
         self._cells = []
         self._cells_by_id = {}
 
@@ -331,8 +363,18 @@ <h3>Class variables</h3>
 
             self._cells.append(sample_cell)
             self._cells_by_id[sample_cell.id] = sample_cell
+        log.debug(&#39;Cells for Sample: %s were reloaded&#39;, self.eid)
 
     def save(self, force: bool = True) -&gt; None:
+        &#34;&#34;&#34;Save Sample.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Saving Sample: %s...&#39;, self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         request_body = []
@@ -355,6 +397,7 @@ <h3>Class variables</h3>
             },
         )
         self._reload_cells()
+        log.debug(&#39;Sample: %s were saved successfully.&#39;, self.eid)
 
     @classmethod
     def create(
@@ -366,6 +409,22 @@ <h3>Class variables</h3>
         digest: str = None,
         force: bool = True,
     ) -&gt; &#39;Sample&#39;:
+        &#34;&#34;&#34;Create Sample Entity
+
+        Args:
+            cells: Sample&#39;s data
+            template: template for Sample creation
+            ancestors: Container or SamplesContainer where create new Sample
+            digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+                If the parameter &#39;force&#39; is true, this parameter is optional.
+                If the parameter &#39;force&#39; is false, this parameter is required.
+            force: Force to create without doing digest check
+
+        Returns:
+            Sample
+        &#34;&#34;&#34;
+        log.debug(&#39;Create Sample: %s &#39;, cls.__name__)
+
         relationships = None
         if template or ancestors:
             relationships = _SampleRelationships(
@@ -406,7 +465,24 @@ <h3>Static methods</h3>
 <span>def <span class="ident">create</span></span>(<span>*, cells: Optional[List[<a title="signals_notebook.entities.samples.cell.SampleCell" href="cell.html#signals_notebook.entities.samples.cell.SampleCell">SampleCell</a>]] = None, template: Optional[ForwardRef('<a title="signals_notebook.entities.samples.sample.Sample" href="#signals_notebook.entities.samples.sample.Sample">Sample</a>')] = None, ancestors: Optional[List[Union[<a title="signals_notebook.entities.container.Container" href="../container.html#signals_notebook.entities.container.Container">Container</a>, ForwardRef('SamplesContainer')]]] = None, digest: str = None, force: bool = True) ‑> <a title="signals_notebook.entities.samples.sample.Sample" href="#signals_notebook.entities.samples.sample.Sample">Sample</a></span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Create Sample Entity</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>cells</code></strong></dt>
+<dd>Sample's data</dd>
+<dt><strong><code>template</code></strong></dt>
+<dd>template for Sample creation</dd>
+<dt><strong><code>ancestors</code></strong></dt>
+<dd>Container or SamplesContainer where create new Sample</dd>
+<dt><strong><code>digest</code></strong></dt>
+<dd>Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+If the parameter 'force' is true, this parameter is optional.
+If the parameter 'force' is false, this parameter is required.</dd>
+<dt><strong><code>force</code></strong></dt>
+<dd>Force to create without doing digest check</dd>
+</dl>
+<h2 id="returns">Returns</h2>
+<p>Sample</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
@@ -421,6 +497,22 @@ <h3>Static methods</h3>
     digest: str = None,
     force: bool = True,
 ) -&gt; &#39;Sample&#39;:
+    &#34;&#34;&#34;Create Sample Entity
+
+    Args:
+        cells: Sample&#39;s data
+        template: template for Sample creation
+        ancestors: Container or SamplesContainer where create new Sample
+        digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+            If the parameter &#39;force&#39; is true, this parameter is optional.
+            If the parameter &#39;force&#39; is false, this parameter is required.
+        force: Force to create without doing digest check
+
+    Returns:
+        Sample
+    &#34;&#34;&#34;
+    log.debug(&#39;Create Sample: %s &#39;, cls.__name__)
+
     relationships = None
     if template or ancestors:
         relationships = _SampleRelationships(
@@ -444,17 +536,70 @@ <h3>Static methods</h3>
 </details>
 </dd>
 </dl>
+<h3>Methods</h3>
+<dl>
+<dt id="signals_notebook.entities.samples.sample.Sample.save"><code class="name flex">
+<span>def <span class="ident">save</span></span>(<span>self, force: bool = True) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Save Sample.</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>force</code></strong></dt>
+<dd>Force to update content without doing digest check.</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def save(self, force: bool = True) -&gt; None:
+    &#34;&#34;&#34;Save Sample.
+
+    Args:
+        force: Force to update content without doing digest check.
+
+    Returns:
+
+    &#34;&#34;&#34;
+    log.debug(&#39;Saving Sample: %s...&#39;, self.eid)
+    api = SignalsNotebookApi.get_default_api()
+
+    request_body = []
+    for item in self._cells:
+        if item.is_changed:
+            request_body.append(item.representation_for_update.dict(exclude_none=True))
+
+    if not request_body:
+        return
+
+    api.call(
+        method=&#39;PATCH&#39;,
+        path=(self._get_samples_endpoint(), self.eid, &#39;properties&#39;),
+        params={
+            &#39;force&#39;: json.dumps(force),
+            &#39;value&#39;: &#39;normalized&#39;,
+        },
+        json={
+            &#39;data&#39;: {&#39;attributes&#39;: {&#39;data&#39;: request_body}},
+        },
+    )
+    self._reload_cells()
+    log.debug(&#39;Sample: %s were saved successfully.&#39;, self.eid)</code></pre>
+</details>
+</dd>
+</dl>
 <h3>Inherited members</h3>
 <ul class="hlist">
 <li><code><b><a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></b></code>:
 <ul class="hlist">
 <li><code><a title="signals_notebook.entities.entity.Entity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.dump_templates" href="../entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_html" href="../entity.html#signals_notebook.entities.entity.Entity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.refresh" href="../entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
-<li><code><a title="signals_notebook.entities.entity.Entity.save" href="../entity.html#signals_notebook.entities.entity.Entity.save">save</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.set_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.short_description" href="../entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
 </ul>
@@ -531,6 +676,7 @@ <h4><code><a title="signals_notebook.entities.samples.sample.Response[SampleCell
 <h4><code><a title="signals_notebook.entities.samples.sample.Sample" href="#signals_notebook.entities.samples.sample.Sample">Sample</a></code></h4>
 <ul class="">
 <li><code><a title="signals_notebook.entities.samples.sample.Sample.create" href="#signals_notebook.entities.samples.sample.Sample.create">create</a></code></li>
+<li><code><a title="signals_notebook.entities.samples.sample.Sample.save" href="#signals_notebook.entities.samples.sample.Sample.save">save</a></code></li>
 <li><code><a title="signals_notebook.entities.samples.sample.Sample.type" href="#signals_notebook.entities.samples.sample.Sample.type">type</a></code></li>
 </ul>
 </li>
diff --git a/docs/signals_notebook/entities/samples/samples_container.html b/docs/signals_notebook/entities/samples/samples_container.html
index a1fa72ff..acf4062d 100644
--- a/docs/signals_notebook/entities/samples/samples_container.html
+++ b/docs/signals_notebook/entities/samples/samples_container.html
@@ -27,6 +27,7 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.samples_contain
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">import csv
+import logging
 from io import StringIO
 from typing import cast, ClassVar, Dict, Generator, List, Literal, Union
 from uuid import UUID
@@ -39,6 +40,8 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.samples_contain
 from signals_notebook.entities.contentful_entity import ContentfulEntity
 from signals_notebook.jinja_env import env
 
+log = logging.getLogger(__name__)
+
 
 class SamplesContainerResponse(Response[Sample]):
     pass
@@ -75,9 +78,16 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.samples_contain
         return EntityType.SAMPLES_CONTAINER
 
     def get_content(self) -&gt; File:
+        &#34;&#34;&#34;Get SamplesContainer content
+
+        Returns:
+            File
+        &#34;&#34;&#34;
         return super()._get_content()
 
     def _reload_samples(self) -&gt; None:
+        log.debug(&#39;Reloading samples for Samples Container: %s...&#39;, self.eid)
+
         self._samples = []
         self._samples_by_id = {}
         for item in self._get_samples():
@@ -86,8 +96,10 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.samples_contain
 
             self._samples.append(item)
             self._samples_by_id[sample.eid] = sample
+        log.debug(&#39;Data in Samples Container: %s were reloaded&#39;, self.eid)
 
     def _get_samples(self) -&gt; Generator[Sample, None, None]:
+        log.debug(&#39;Getting samples for Samples Container: %s...&#39;, self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         response = api.call(
@@ -107,19 +119,37 @@ <h1 class="title">Module <code>signals_notebook.entities.samples.samples_contain
 
             result = SamplesContainerResponse(**response.json())
             yield from [cast(ResponseData, item).body for item in result.data]
+        log.debug(&#39;Samples for SamplesContainer: %s were got successfully.&#39;, self.eid)
 
     def save(self, force: bool = True) -&gt; None:
+        &#34;&#34;&#34;Save SamplesContainer content.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Saving SamplesContainer: %s...&#39;, self.eid)
         for item in self._samples:
             item.save(force=force)
         self._reload_samples()
+        log.debug(&#39;SamplesContainer: %s were saved successfully.&#39;, self.eid)
 
     def get_html(self) -&gt; str:
+        &#34;&#34;&#34;Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        &#34;&#34;&#34;
         file = self.get_content()
         content = StringIO(file.content.decode(&#39;utf-8&#39;))
         csv_data = list(csv.reader(content))
         table_head = csv_data[0]
         rows = csv_data[1:]
         template = env.get_template(self._template_name)
+        log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
         return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
 </details>
 </section>
@@ -209,9 +239,16 @@ <h3>Class variables</h3>
         return EntityType.SAMPLES_CONTAINER
 
     def get_content(self) -&gt; File:
+        &#34;&#34;&#34;Get SamplesContainer content
+
+        Returns:
+            File
+        &#34;&#34;&#34;
         return super()._get_content()
 
     def _reload_samples(self) -&gt; None:
+        log.debug(&#39;Reloading samples for Samples Container: %s...&#39;, self.eid)
+
         self._samples = []
         self._samples_by_id = {}
         for item in self._get_samples():
@@ -220,8 +257,10 @@ <h3>Class variables</h3>
 
             self._samples.append(item)
             self._samples_by_id[sample.eid] = sample
+        log.debug(&#39;Data in Samples Container: %s were reloaded&#39;, self.eid)
 
     def _get_samples(self) -&gt; Generator[Sample, None, None]:
+        log.debug(&#39;Getting samples for Samples Container: %s...&#39;, self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         response = api.call(
@@ -241,19 +280,37 @@ <h3>Class variables</h3>
 
             result = SamplesContainerResponse(**response.json())
             yield from [cast(ResponseData, item).body for item in result.data]
+        log.debug(&#39;Samples for SamplesContainer: %s were got successfully.&#39;, self.eid)
 
     def save(self, force: bool = True) -&gt; None:
+        &#34;&#34;&#34;Save SamplesContainer content.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Saving SamplesContainer: %s...&#39;, self.eid)
         for item in self._samples:
             item.save(force=force)
         self._reload_samples()
+        log.debug(&#39;SamplesContainer: %s were saved successfully.&#39;, self.eid)
 
     def get_html(self) -&gt; str:
+        &#34;&#34;&#34;Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        &#34;&#34;&#34;
         file = self.get_content()
         content = StringIO(file.content.decode(&#39;utf-8&#39;))
         csv_data = list(csv.reader(content))
         table_head = csv_data[0]
         rows = csv_data[1:]
         template = env.get_template(self._template_name)
+        log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
         return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
 </details>
 <h3>Ancestors</h3>
@@ -277,15 +334,81 @@ <h3>Methods</h3>
 <span>def <span class="ident">get_content</span></span>(<span>self) ‑> <a title="signals_notebook.common_types.File" href="../../common_types.html#signals_notebook.common_types.File">File</a></span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get SamplesContainer content</p>
+<h2 id="returns">Returns</h2>
+<p>File</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">def get_content(self) -&gt; File:
+    &#34;&#34;&#34;Get SamplesContainer content
+
+    Returns:
+        File
+    &#34;&#34;&#34;
     return super()._get_content()</code></pre>
 </details>
 </dd>
+<dt id="signals_notebook.entities.samples.samples_container.SamplesContainer.get_html"><code class="name flex">
+<span>def <span class="ident">get_html</span></span>(<span>self) ‑> str</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get in HTML format</p>
+<h2 id="returns">Returns</h2>
+<p>Rendered HTML in string format</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_html(self) -&gt; str:
+    &#34;&#34;&#34;Get in HTML format
+
+    Returns:
+        Rendered HTML in string format
+    &#34;&#34;&#34;
+    file = self.get_content()
+    content = StringIO(file.content.decode(&#39;utf-8&#39;))
+    csv_data = list(csv.reader(content))
+    table_head = csv_data[0]
+    rows = csv_data[1:]
+    template = env.get_template(self._template_name)
+    log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
+    return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.entities.samples.samples_container.SamplesContainer.save"><code class="name flex">
+<span>def <span class="ident">save</span></span>(<span>self, force: bool = True) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Save SamplesContainer content.</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>force</code></strong></dt>
+<dd>Force to update content without doing digest check.</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def save(self, force: bool = True) -&gt; None:
+    &#34;&#34;&#34;Save SamplesContainer content.
+
+    Args:
+        force: Force to update content without doing digest check.
+
+    Returns:
+
+    &#34;&#34;&#34;
+    log.debug(&#39;Saving SamplesContainer: %s...&#39;, self.eid)
+    for item in self._samples:
+        item.save(force=force)
+    self._reload_samples()
+    log.debug(&#39;SamplesContainer: %s were saved successfully.&#39;, self.eid)</code></pre>
+</details>
+</dd>
 </dl>
 <h3>Inherited members</h3>
 <ul class="hlist">
@@ -294,13 +417,12 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="../entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.load" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.load">load</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.refresh" href="../entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.save" href="../entity.html#signals_notebook.entities.entity.Entity.save">save</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.set_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.short_description" href="../entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
 </ul>
@@ -370,6 +492,8 @@ <h4><code><a title="signals_notebook.entities.samples.samples_container.Response
 <h4><code><a title="signals_notebook.entities.samples.samples_container.SamplesContainer" href="#signals_notebook.entities.samples.samples_container.SamplesContainer">SamplesContainer</a></code></h4>
 <ul class="">
 <li><code><a title="signals_notebook.entities.samples.samples_container.SamplesContainer.get_content" href="#signals_notebook.entities.samples.samples_container.SamplesContainer.get_content">get_content</a></code></li>
+<li><code><a title="signals_notebook.entities.samples.samples_container.SamplesContainer.get_html" href="#signals_notebook.entities.samples.samples_container.SamplesContainer.get_html">get_html</a></code></li>
+<li><code><a title="signals_notebook.entities.samples.samples_container.SamplesContainer.save" href="#signals_notebook.entities.samples.samples_container.SamplesContainer.save">save</a></code></li>
 <li><code><a title="signals_notebook.entities.samples.samples_container.SamplesContainer.type" href="#signals_notebook.entities.samples.samples_container.SamplesContainer.type">type</a></code></li>
 </ul>
 </li>
diff --git a/docs/signals_notebook/entities/spotfire.html b/docs/signals_notebook/entities/spotfire.html
index b5639426..6d4150b1 100644
--- a/docs/signals_notebook/entities/spotfire.html
+++ b/docs/signals_notebook/entities/spotfire.html
@@ -265,6 +265,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/stoichiometry/data_grid.html b/docs/signals_notebook/entities/stoichiometry/data_grid.html
index 0938912f..5e1fee93 100644
--- a/docs/signals_notebook/entities/stoichiometry/data_grid.html
+++ b/docs/signals_notebook/entities/stoichiometry/data_grid.html
@@ -101,7 +101,6 @@ <h1 class="title">Module <code>signals_notebook.entities.stoichiometry.data_grid
         if isinstance(index, UUID):
             return self._rows_by_id[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     @property
@@ -916,7 +915,6 @@ <h2 id="args">Args</h2>
         if isinstance(index, UUID):
             return self._rows_by_id[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     @property
diff --git a/docs/signals_notebook/entities/tables/row.html b/docs/signals_notebook/entities/tables/row.html
index 7aa1255b..0a81c229 100644
--- a/docs/signals_notebook/entities/tables/row.html
+++ b/docs/signals_notebook/entities/tables/row.html
@@ -179,7 +179,6 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.row</code></h1>
         if isinstance(index, UUID):
             return self._cells_dict[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     def __iter__(self):
@@ -497,7 +496,6 @@ <h3>Class variables</h3>
         if isinstance(index, UUID):
             return self._cells_dict[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     def __iter__(self):
diff --git a/docs/signals_notebook/entities/tables/table.html b/docs/signals_notebook/entities/tables/table.html
index b049f96d..ac816a0a 100644
--- a/docs/signals_notebook/entities/tables/table.html
+++ b/docs/signals_notebook/entities/tables/table.html
@@ -26,8 +26,10 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
 <summary>
 <span>Expand source code</span>
 </summary>
-<pre><code class="python">import json
+<pre><code class="python">import cgi
+import json
 import logging
+from enum import Enum
 from typing import Any, cast, Dict, List, Literal, Union
 from uuid import UUID
 
@@ -35,10 +37,9 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
 from pydantic import Field, PrivateAttr
 
 from signals_notebook.api import SignalsNotebookApi
-from signals_notebook.common_types import DataList, EntityType, Response, ResponseData, EID
-from signals_notebook.entities import EntityStore
+from signals_notebook.common_types import DataList, EntityType, File, Response, ResponseData
+from signals_notebook.entities import Entity, EntityStore
 from signals_notebook.entities.container import Container
-from signals_notebook.entities.contentful_entity import ContentfulEntity
 from signals_notebook.entities.tables.cell import Cell, CellContentDict, ColumnDefinitions, GenericColumnDefinition
 from signals_notebook.entities.tables.row import ChangeRowRequest, Row
 from signals_notebook.jinja_env import env
@@ -59,7 +60,11 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
     pass
 
 
-class Table(ContentfulEntity):
+class Table(Entity):
+    class ContentType(str, Enum):
+        JSON = &#39;application/json&#39;
+        CSV = &#39;text/csv&#39;
+
     type: Literal[EntityType.GRID] = Field(allow_mutation=False)
     _rows: List[Row] = PrivateAttr(default=[])
     _rows_by_id: Dict[UUID, Row] = PrivateAttr(default={})
@@ -130,7 +135,7 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
         &#34;&#34;&#34;Get as data table
 
         Args:
-            use_labels: use cels names
+            use_labels: use cells names
 
         Returns:
             pd.DataFrame
@@ -177,7 +182,6 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
         if isinstance(index, UUID):
             return self._rows_by_id[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     def __iter__(self):
@@ -299,6 +303,114 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
             log.debug(&#39;KeyError were caught. Default value returned&#39;)
             return default
 
+    def get_content(self, content_type: str = ContentType.CSV.value) -&gt; File:
+        &#34;&#34;&#34;Get Table content
+
+        Args:
+            content_type: Export resource format
+
+        Returns:
+
+        &#34;&#34;&#34;
+        self.ContentType(content_type)
+        if content_type == self.ContentType.JSON.value:
+            rows = []
+            for item in self:
+                row = {}
+                for cell in item:
+                    row[cell.name] = cell.content.dict()
+                rows.append(row)
+            return File(
+                name=f&#39;{self.name}.json&#39;,
+                content=json.dumps({&#39;data&#39;: rows}, default=str).encode(&#39;utf-8&#39;),
+                content_type=content_type,
+            )
+
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Get content for: %s| %s&#39;, self.__class__.__name__, self.eid)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(self._get_endpoint(), self.eid, &#39;export&#39;),
+            params={
+                &#39;format&#39;: None,
+            },
+        )
+
+        content_disposition = response.headers.get(&#39;content-disposition&#39;, &#39;&#39;)
+        _, params = cgi.parse_header(content_disposition)
+
+        return File(
+            name=params[&#39;filename&#39;],
+            content=response.content,
+            content_type=response.headers.get(&#39;content-type&#39;),
+        )
+
+    @classmethod
+    def create(
+        cls,
+        *,
+        container: Container,
+        name: str,
+        content: List[Dict[str, CellContentDict]] = None,
+        template: str = None,
+        digest: str = None,
+        force: bool = True,
+    ) -&gt; Entity:
+        &#34;&#34;&#34;Create Table Entity
+
+        Args:
+            container: Container where create new Table
+            name: file name
+            content: Table content
+            template: template for table creation
+            digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+            force: Force to post attachment
+
+        Returns:
+            Table
+        &#34;&#34;&#34;
+        log.debug(&#39;Create Table: %s...&#39;, cls.__name__)
+        if template:
+            api = SignalsNotebookApi.get_default_api()
+            request = {
+                &#39;data&#39;: {
+                    &#39;type&#39;: EntityType.GRID,
+                    &#39;attributes&#39;: {&#39;name&#39;: name},
+                    &#39;relationships&#39;: {
+                        &#39;ancestors&#39;: {&#39;data&#39;: [{&#39;type&#39;: EntityType.EXPERIMENT, &#39;id&#39;: container.eid}]},
+                        &#39;template&#39;: {&#39;data&#39;: {&#39;type&#39;: EntityType.GRID, &#39;id&#39;: template}},
+                    },
+                }
+            }
+
+            response = api.call(
+                method=&#39;POST&#39;,
+                path=(cls._get_endpoint(),),
+                params={
+                    &#39;digest&#39;: digest,
+                    &#39;force&#39;: json.dumps(force),
+                },
+                json=request,
+            )
+            result = TableResponse(**response.json())
+            table = cast(ResponseData, result.data).body
+            log.debug(&#39;Entity: %s was created.&#39;, cls.__name__)
+            if content:
+                for row in content:
+                    table.add_row(row)
+                table.save()
+            return table
+
+        log.debug(&#39;There is no needful template. Table will be uploaded as *.csv File...&#39;)
+        log.debug(&#39;Create table: %s with name: %s in Container: %s&#39;, cls.__name__, name, container.eid)
+        return container.add_child(
+            name=name,
+            content=json.dumps({&#39;data&#39;: content}, default=str).encode(&#39;utf-8&#39;),
+            content_type=cls.ContentType.JSON,
+            force=force,
+        )
+
     def get_html(self) -&gt; str:
         &#34;&#34;&#34;Get in HTML format
 
@@ -326,7 +438,118 @@ <h1 class="title">Module <code>signals_notebook.entities.tables.table</code></h1
         template = env.get_template(self._template_name)
         log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
 
-        return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
+        return template.render(name=self.name, table_head=table_head, rows=rows)
+
+    def dump(self, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Table entity
+
+        Args:
+            base_path: content path where create dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Dumping table: %s with name: %s...&#39;, self.eid, self.name)
+
+        content = self.get_content(content_type=self.ContentType.JSON)
+        column_definitions = self.get_column_definitions_list()
+
+        metadata = {
+            &#39;file_name&#39;: content.name,
+            &#39;content_type&#39;: content.content_type,
+            &#39;columns&#39;: [item.title for item in column_definitions],
+            **{k: v for k, v in self.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+        }
+        fs_handler.write(fs_handler.join_path(base_path, self.eid, &#39;metadata.json&#39;), json.dumps(metadata, default=str))
+        file_name = content.name
+        data = content.content
+        fs_handler.write(fs_handler.join_path(base_path, self.eid, file_name), data)
+        log.debug(&#39;Table: %s was dumped successfully&#39;, self.eid, self.name)
+
+    @classmethod
+    def load(cls, path: str, fs_handler: FSHandler, parent: Container) -&gt; None:
+        &#34;&#34;&#34;Load Table entity
+
+        Args:
+            path: content path
+            fs_handler: FSHandler
+            parent: Container where load Table entity
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Loading table from dump...&#39;)
+        metadata_path = fs_handler.join_path(path, &#39;metadata.json&#39;)
+        metadata = json.loads(fs_handler.read(metadata_path))
+        content_path = fs_handler.join_path(path, metadata[&#39;file_name&#39;])
+        content_bytes = fs_handler.read(content_path)
+        content = json.loads(content_bytes)
+        rows = content[&#39;data&#39;]
+        column_definitions = metadata.get(&#39;columns&#39;)
+        templates = EntityStore.get_list(
+            include_types=[EntityType.GRID], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+
+        file_creation = True
+        for item in templates:
+            template = cast(&#39;Table&#39;, item)
+            template_column_definitions = template.get_column_definitions_list()
+            template_columns = [item.title for item in template_column_definitions]
+            if set(template_columns) == set(column_definitions):
+                file_creation = False
+                cls.create(
+                    container=parent,
+                    name=metadata[&#39;name&#39;],
+                    template=template.eid,
+                    content=rows,
+                )
+                break
+
+        if file_creation:
+            cls.create(container=parent, name=metadata[&#39;name&#39;], content=rows, force=True)
+        log.debug(&#39;Table was loaded to Container: %s&#39;, parent.eid)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Table templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+
+        try:
+            for item in templates:
+                template = cast(&#39;Table&#39;, item)
+                content = template.get_content(content_type=cls.ContentType.JSON)
+                column_definitions = template.get_column_definitions_list()
+                metadata = {
+                    &#39;file_name&#39;: content.name,
+                    &#39;content_type&#39;: content.content_type,
+                    &#39;columns&#39;: [item.title for item in column_definitions],
+                    **{k: v for k, v in template.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+                }
+                fs_handler.write(
+                    fs_handler.join_path(base_path, &#39;templates&#39;, entity_type, f&#39;metadata_{template.name}.json&#39;),
+                    json.dumps(metadata),
+                )
+        except TypeError:
+            pass
+
+
+class TableResponse(Response[Table]):
+    pass</code></pre>
 </details>
 </section>
 <section>
@@ -505,6 +728,41 @@ <h3>Class variables</h3>
 </dd>
 </dl>
 </dd>
+<dt id="signals_notebook.entities.tables.table.Response[Table]"><code class="flex name class">
+<span>class <span class="ident">Response[Table]</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.common_types.Response" href="../../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Subclasses</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.tables.table.TableResponse" href="#signals_notebook.entities.tables.table.TableResponse">TableResponse</a></li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.tables.table.Response[Table].Config"><code class="name">var <span class="ident">Config</span></code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.tables.table.Response[Table].data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[<a title="signals_notebook.entities.tables.table.Table" href="#signals_notebook.entities.tables.table.Table">Table</a>], List[pydantic.generics.ResponseData[<a title="signals_notebook.entities.tables.table.Table" href="#signals_notebook.entities.tables.table.Table">Table</a>]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.tables.table.Response[Table].links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
 <dt id="signals_notebook.entities.tables.table.Table"><code class="flex name class">
 <span>class <span class="ident">Table</span></span>
 <span>(</span><span>**data: Any)</span>
@@ -516,7 +774,11 @@ <h3>Class variables</h3>
 <summary>
 <span>Expand source code</span>
 </summary>
-<pre><code class="python">class Table(ContentfulEntity):
+<pre><code class="python">class Table(Entity):
+    class ContentType(str, Enum):
+        JSON = &#39;application/json&#39;
+        CSV = &#39;text/csv&#39;
+
     type: Literal[EntityType.GRID] = Field(allow_mutation=False)
     _rows: List[Row] = PrivateAttr(default=[])
     _rows_by_id: Dict[UUID, Row] = PrivateAttr(default={})
@@ -587,7 +849,7 @@ <h3>Class variables</h3>
         &#34;&#34;&#34;Get as data table
 
         Args:
-            use_labels: use cels names
+            use_labels: use cells names
 
         Returns:
             pd.DataFrame
@@ -634,7 +896,6 @@ <h3>Class variables</h3>
         if isinstance(index, UUID):
             return self._rows_by_id[index]
 
-        log.exception(&#39;IndexError were caught. Invalid index&#39;)
         raise IndexError(&#39;Invalid index&#39;)
 
     def __iter__(self):
@@ -756,6 +1017,114 @@ <h3>Class variables</h3>
             log.debug(&#39;KeyError were caught. Default value returned&#39;)
             return default
 
+    def get_content(self, content_type: str = ContentType.CSV.value) -&gt; File:
+        &#34;&#34;&#34;Get Table content
+
+        Args:
+            content_type: Export resource format
+
+        Returns:
+
+        &#34;&#34;&#34;
+        self.ContentType(content_type)
+        if content_type == self.ContentType.JSON.value:
+            rows = []
+            for item in self:
+                row = {}
+                for cell in item:
+                    row[cell.name] = cell.content.dict()
+                rows.append(row)
+            return File(
+                name=f&#39;{self.name}.json&#39;,
+                content=json.dumps({&#39;data&#39;: rows}, default=str).encode(&#39;utf-8&#39;),
+                content_type=content_type,
+            )
+
+        api = SignalsNotebookApi.get_default_api()
+        log.debug(&#39;Get content for: %s| %s&#39;, self.__class__.__name__, self.eid)
+
+        response = api.call(
+            method=&#39;GET&#39;,
+            path=(self._get_endpoint(), self.eid, &#39;export&#39;),
+            params={
+                &#39;format&#39;: None,
+            },
+        )
+
+        content_disposition = response.headers.get(&#39;content-disposition&#39;, &#39;&#39;)
+        _, params = cgi.parse_header(content_disposition)
+
+        return File(
+            name=params[&#39;filename&#39;],
+            content=response.content,
+            content_type=response.headers.get(&#39;content-type&#39;),
+        )
+
+    @classmethod
+    def create(
+        cls,
+        *,
+        container: Container,
+        name: str,
+        content: List[Dict[str, CellContentDict]] = None,
+        template: str = None,
+        digest: str = None,
+        force: bool = True,
+    ) -&gt; Entity:
+        &#34;&#34;&#34;Create Table Entity
+
+        Args:
+            container: Container where create new Table
+            name: file name
+            content: Table content
+            template: template for table creation
+            digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+            force: Force to post attachment
+
+        Returns:
+            Table
+        &#34;&#34;&#34;
+        log.debug(&#39;Create Table: %s...&#39;, cls.__name__)
+        if template:
+            api = SignalsNotebookApi.get_default_api()
+            request = {
+                &#39;data&#39;: {
+                    &#39;type&#39;: EntityType.GRID,
+                    &#39;attributes&#39;: {&#39;name&#39;: name},
+                    &#39;relationships&#39;: {
+                        &#39;ancestors&#39;: {&#39;data&#39;: [{&#39;type&#39;: EntityType.EXPERIMENT, &#39;id&#39;: container.eid}]},
+                        &#39;template&#39;: {&#39;data&#39;: {&#39;type&#39;: EntityType.GRID, &#39;id&#39;: template}},
+                    },
+                }
+            }
+
+            response = api.call(
+                method=&#39;POST&#39;,
+                path=(cls._get_endpoint(),),
+                params={
+                    &#39;digest&#39;: digest,
+                    &#39;force&#39;: json.dumps(force),
+                },
+                json=request,
+            )
+            result = TableResponse(**response.json())
+            table = cast(ResponseData, result.data).body
+            log.debug(&#39;Entity: %s was created.&#39;, cls.__name__)
+            if content:
+                for row in content:
+                    table.add_row(row)
+                table.save()
+            return table
+
+        log.debug(&#39;There is no needful template. Table will be uploaded as *.csv File...&#39;)
+        log.debug(&#39;Create table: %s with name: %s in Container: %s&#39;, cls.__name__, name, container.eid)
+        return container.add_child(
+            name=name,
+            content=json.dumps({&#39;data&#39;: content}, default=str).encode(&#39;utf-8&#39;),
+            content_type=cls.ContentType.JSON,
+            force=force,
+        )
+
     def get_html(self) -&gt; str:
         &#34;&#34;&#34;Get in HTML format
 
@@ -783,23 +1152,345 @@ <h3>Class variables</h3>
         template = env.get_template(self._template_name)
         log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
 
-        return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
+        return template.render(name=self.name, table_head=table_head, rows=rows)
+
+    def dump(self, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Table entity
+
+        Args:
+            base_path: content path where create dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Dumping table: %s with name: %s...&#39;, self.eid, self.name)
+
+        content = self.get_content(content_type=self.ContentType.JSON)
+        column_definitions = self.get_column_definitions_list()
+
+        metadata = {
+            &#39;file_name&#39;: content.name,
+            &#39;content_type&#39;: content.content_type,
+            &#39;columns&#39;: [item.title for item in column_definitions],
+            **{k: v for k, v in self.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+        }
+        fs_handler.write(fs_handler.join_path(base_path, self.eid, &#39;metadata.json&#39;), json.dumps(metadata, default=str))
+        file_name = content.name
+        data = content.content
+        fs_handler.write(fs_handler.join_path(base_path, self.eid, file_name), data)
+        log.debug(&#39;Table: %s was dumped successfully&#39;, self.eid, self.name)
+
+    @classmethod
+    def load(cls, path: str, fs_handler: FSHandler, parent: Container) -&gt; None:
+        &#34;&#34;&#34;Load Table entity
+
+        Args:
+            path: content path
+            fs_handler: FSHandler
+            parent: Container where load Table entity
+
+        Returns:
+
+        &#34;&#34;&#34;
+        log.debug(&#39;Loading table from dump...&#39;)
+        metadata_path = fs_handler.join_path(path, &#39;metadata.json&#39;)
+        metadata = json.loads(fs_handler.read(metadata_path))
+        content_path = fs_handler.join_path(path, metadata[&#39;file_name&#39;])
+        content_bytes = fs_handler.read(content_path)
+        content = json.loads(content_bytes)
+        rows = content[&#39;data&#39;]
+        column_definitions = metadata.get(&#39;columns&#39;)
+        templates = EntityStore.get_list(
+            include_types=[EntityType.GRID], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+
+        file_creation = True
+        for item in templates:
+            template = cast(&#39;Table&#39;, item)
+            template_column_definitions = template.get_column_definitions_list()
+            template_columns = [item.title for item in template_column_definitions]
+            if set(template_columns) == set(column_definitions):
+                file_creation = False
+                cls.create(
+                    container=parent,
+                    name=metadata[&#39;name&#39;],
+                    template=template.eid,
+                    content=rows,
+                )
+                break
+
+        if file_creation:
+            cls.create(container=parent, name=metadata[&#39;name&#39;], content=rows, force=True)
+        log.debug(&#39;Table was loaded to Container: %s&#39;, parent.eid)
+
+    @classmethod
+    def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+        &#34;&#34;&#34;Dump Table templates
+
+        Args:
+            base_path: content path where create templates dump
+            fs_handler: FSHandler
+
+        Returns:
+
+        &#34;&#34;&#34;
+        from signals_notebook.entities import EntityStore
+
+        entity_type = cls._get_entity_type()
+
+        templates = EntityStore.get_list(
+            include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+        )
+
+        try:
+            for item in templates:
+                template = cast(&#39;Table&#39;, item)
+                content = template.get_content(content_type=cls.ContentType.JSON)
+                column_definitions = template.get_column_definitions_list()
+                metadata = {
+                    &#39;file_name&#39;: content.name,
+                    &#39;content_type&#39;: content.content_type,
+                    &#39;columns&#39;: [item.title for item in column_definitions],
+                    **{k: v for k, v in template.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+                }
+                fs_handler.write(
+                    fs_handler.join_path(base_path, &#39;templates&#39;, entity_type, f&#39;metadata_{template.name}.json&#39;),
+                    json.dumps(metadata),
+                )
+        except TypeError:
+            pass</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
-<li><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></li>
 <li><a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></li>
 <li>pydantic.main.BaseModel</li>
 <li>pydantic.utils.Representation</li>
-<li>abc.ABC</li>
 </ul>
 <h3>Class variables</h3>
 <dl>
+<dt id="signals_notebook.entities.tables.table.Table.ContentType"><code class="name">var <span class="ident">ContentType</span></code></dt>
+<dd>
+<div class="desc"><p>An enumeration.</p></div>
+</dd>
 <dt id="signals_notebook.entities.tables.table.Table.type"><code class="name">var <span class="ident">type</span> : Literal[<EntityType.GRID: 'grid'>]</code></dt>
 <dd>
 <div class="desc"></div>
 </dd>
 </dl>
+<h3>Static methods</h3>
+<dl>
+<dt id="signals_notebook.entities.tables.table.Table.create"><code class="name flex">
+<span>def <span class="ident">create</span></span>(<span>*, container: <a title="signals_notebook.entities.container.Container" href="../container.html#signals_notebook.entities.container.Container">Container</a>, name: str, content: List[Dict[str, <a title="signals_notebook.entities.tables.cell.CellContentDict" href="cell.html#signals_notebook.entities.tables.cell.CellContentDict">CellContentDict</a>]] = None, template: str = None, digest: str = None, force: bool = True) ‑> <a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create Table Entity</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>container</code></strong></dt>
+<dd>Container where create new Table</dd>
+<dt><strong><code>name</code></strong></dt>
+<dd>file name</dd>
+<dt><strong><code>content</code></strong></dt>
+<dd>Table content</dd>
+<dt><strong><code>template</code></strong></dt>
+<dd>template for table creation</dd>
+<dt><strong><code>digest</code></strong></dt>
+<dd>Indicate digest of entity. It is used to avoid conflict while concurrent editing.</dd>
+<dt><strong><code>force</code></strong></dt>
+<dd>Force to post attachment</dd>
+</dl>
+<h2 id="returns">Returns</h2>
+<p>Table</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def create(
+    cls,
+    *,
+    container: Container,
+    name: str,
+    content: List[Dict[str, CellContentDict]] = None,
+    template: str = None,
+    digest: str = None,
+    force: bool = True,
+) -&gt; Entity:
+    &#34;&#34;&#34;Create Table Entity
+
+    Args:
+        container: Container where create new Table
+        name: file name
+        content: Table content
+        template: template for table creation
+        digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+        force: Force to post attachment
+
+    Returns:
+        Table
+    &#34;&#34;&#34;
+    log.debug(&#39;Create Table: %s...&#39;, cls.__name__)
+    if template:
+        api = SignalsNotebookApi.get_default_api()
+        request = {
+            &#39;data&#39;: {
+                &#39;type&#39;: EntityType.GRID,
+                &#39;attributes&#39;: {&#39;name&#39;: name},
+                &#39;relationships&#39;: {
+                    &#39;ancestors&#39;: {&#39;data&#39;: [{&#39;type&#39;: EntityType.EXPERIMENT, &#39;id&#39;: container.eid}]},
+                    &#39;template&#39;: {&#39;data&#39;: {&#39;type&#39;: EntityType.GRID, &#39;id&#39;: template}},
+                },
+            }
+        }
+
+        response = api.call(
+            method=&#39;POST&#39;,
+            path=(cls._get_endpoint(),),
+            params={
+                &#39;digest&#39;: digest,
+                &#39;force&#39;: json.dumps(force),
+            },
+            json=request,
+        )
+        result = TableResponse(**response.json())
+        table = cast(ResponseData, result.data).body
+        log.debug(&#39;Entity: %s was created.&#39;, cls.__name__)
+        if content:
+            for row in content:
+                table.add_row(row)
+            table.save()
+        return table
+
+    log.debug(&#39;There is no needful template. Table will be uploaded as *.csv File...&#39;)
+    log.debug(&#39;Create table: %s with name: %s in Container: %s&#39;, cls.__name__, name, container.eid)
+    return container.add_child(
+        name=name,
+        content=json.dumps({&#39;data&#39;: content}, default=str).encode(&#39;utf-8&#39;),
+        content_type=cls.ContentType.JSON,
+        force=force,
+    )</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.entities.tables.table.Table.dump_templates"><code class="name flex">
+<span>def <span class="ident">dump_templates</span></span>(<span>base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Dump Table templates</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create templates dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def dump_templates(cls, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump Table templates
+
+    Args:
+        base_path: content path where create templates dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
+    from signals_notebook.entities import EntityStore
+
+    entity_type = cls._get_entity_type()
+
+    templates = EntityStore.get_list(
+        include_types=[entity_type], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+    )
+
+    try:
+        for item in templates:
+            template = cast(&#39;Table&#39;, item)
+            content = template.get_content(content_type=cls.ContentType.JSON)
+            column_definitions = template.get_column_definitions_list()
+            metadata = {
+                &#39;file_name&#39;: content.name,
+                &#39;content_type&#39;: content.content_type,
+                &#39;columns&#39;: [item.title for item in column_definitions],
+                **{k: v for k, v in template.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+            }
+            fs_handler.write(
+                fs_handler.join_path(base_path, &#39;templates&#39;, entity_type, f&#39;metadata_{template.name}.json&#39;),
+                json.dumps(metadata),
+            )
+    except TypeError:
+        pass</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.entities.tables.table.Table.load"><code class="name flex">
+<span>def <span class="ident">load</span></span>(<span>path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>, parent: <a title="signals_notebook.entities.container.Container" href="../container.html#signals_notebook.entities.container.Container">Container</a>) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Load Table entity</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>path</code></strong></dt>
+<dd>content path</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+<dt><strong><code>parent</code></strong></dt>
+<dd>Container where load Table entity</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">@classmethod
+def load(cls, path: str, fs_handler: FSHandler, parent: Container) -&gt; None:
+    &#34;&#34;&#34;Load Table entity
+
+    Args:
+        path: content path
+        fs_handler: FSHandler
+        parent: Container where load Table entity
+
+    Returns:
+
+    &#34;&#34;&#34;
+    log.debug(&#39;Loading table from dump...&#39;)
+    metadata_path = fs_handler.join_path(path, &#39;metadata.json&#39;)
+    metadata = json.loads(fs_handler.read(metadata_path))
+    content_path = fs_handler.join_path(path, metadata[&#39;file_name&#39;])
+    content_bytes = fs_handler.read(content_path)
+    content = json.loads(content_bytes)
+    rows = content[&#39;data&#39;]
+    column_definitions = metadata.get(&#39;columns&#39;)
+    templates = EntityStore.get_list(
+        include_types=[EntityType.GRID], include_options=[EntityStore.IncludeOptions.TEMPLATE]
+    )
+
+    file_creation = True
+    for item in templates:
+        template = cast(&#39;Table&#39;, item)
+        template_column_definitions = template.get_column_definitions_list()
+        template_columns = [item.title for item in template_column_definitions]
+        if set(template_columns) == set(column_definitions):
+            file_creation = False
+            cls.create(
+                container=parent,
+                name=metadata[&#39;name&#39;],
+                template=template.eid,
+                content=rows,
+            )
+            break
+
+    if file_creation:
+        cls.create(container=parent, name=metadata[&#39;name&#39;], content=rows, force=True)
+    log.debug(&#39;Table was loaded to Container: %s&#39;, parent.eid)</code></pre>
+</details>
+</dd>
+</dl>
 <h3>Methods</h3>
 <dl>
 <dt id="signals_notebook.entities.tables.table.Table.add_row"><code class="name flex">
@@ -856,7 +1547,7 @@ <h2 id="args">Args</h2>
 <h2 id="args">Args</h2>
 <dl>
 <dt><strong><code>use_labels</code></strong></dt>
-<dd>use cels names</dd>
+<dd>use cells names</dd>
 </dl>
 <h2 id="returns">Returns</h2>
 <p>pd.DataFrame</p></div>
@@ -868,7 +1559,7 @@ <h2 id="returns">Returns</h2>
     &#34;&#34;&#34;Get as data table
 
     Args:
-        use_labels: use cels names
+        use_labels: use cells names
 
     Returns:
         pd.DataFrame
@@ -972,6 +1663,51 @@ <h2 id="args">Args</h2>
     self._reload_data()</code></pre>
 </details>
 </dd>
+<dt id="signals_notebook.entities.tables.table.Table.dump"><code class="name flex">
+<span>def <span class="ident">dump</span></span>(<span>self, base_path: str, fs_handler: <a title="signals_notebook.utils.fs_handler.FSHandler" href="../../utils/fs_handler.html#signals_notebook.utils.fs_handler.FSHandler">FSHandler</a>) ‑> None</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Dump Table entity</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>base_path</code></strong></dt>
+<dd>content path where create dump</dd>
+<dt><strong><code>fs_handler</code></strong></dt>
+<dd>FSHandler</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def dump(self, base_path: str, fs_handler: FSHandler) -&gt; None:
+    &#34;&#34;&#34;Dump Table entity
+
+    Args:
+        base_path: content path where create dump
+        fs_handler: FSHandler
+
+    Returns:
+
+    &#34;&#34;&#34;
+    log.debug(&#39;Dumping table: %s with name: %s...&#39;, self.eid, self.name)
+
+    content = self.get_content(content_type=self.ContentType.JSON)
+    column_definitions = self.get_column_definitions_list()
+
+    metadata = {
+        &#39;file_name&#39;: content.name,
+        &#39;content_type&#39;: content.content_type,
+        &#39;columns&#39;: [item.title for item in column_definitions],
+        **{k: v for k, v in self.dict().items() if k in (&#39;name&#39;, &#39;description&#39;, &#39;eid&#39;)},
+    }
+    fs_handler.write(fs_handler.join_path(base_path, self.eid, &#39;metadata.json&#39;), json.dumps(metadata, default=str))
+    file_name = content.name
+    data = content.content
+    fs_handler.write(fs_handler.join_path(base_path, self.eid, file_name), data)
+    log.debug(&#39;Table: %s was dumped successfully&#39;, self.eid, self.name)</code></pre>
+</details>
+</dd>
 <dt id="signals_notebook.entities.tables.table.Table.get"><code class="name flex">
 <span>def <span class="ident">get</span></span>(<span>self, value: Union[uuid.UUID, str], default: Any = None) ‑> Union[<a title="signals_notebook.entities.tables.row.Row" href="row.html#signals_notebook.entities.tables.row.Row">Row</a>, Any]</span>
 </code></dt>
@@ -1061,16 +1797,103 @@ <h2 id="returns">Returns</h2>
 </details>
 </dd>
 <dt id="signals_notebook.entities.tables.table.Table.get_content"><code class="name flex">
-<span>def <span class="ident">get_content</span></span>(<span>self)</span>
+<span>def <span class="ident">get_content</span></span>(<span>self, content_type: str = 'text/csv') ‑> <a title="signals_notebook.common_types.File" href="../../common_types.html#signals_notebook.common_types.File">File</a></span>
 </code></dt>
 <dd>
-<div class="desc"></div>
+<div class="desc"><p>Get Table content</p>
+<h2 id="args">Args</h2>
+<dl>
+<dt><strong><code>content_type</code></strong></dt>
+<dd>Export resource format</dd>
+</dl>
+<p>Returns:</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">def get_content(self, content_type: str = ContentType.CSV.value) -&gt; File:
+    &#34;&#34;&#34;Get Table content
+
+    Args:
+        content_type: Export resource format
+
+    Returns:
+
+    &#34;&#34;&#34;
+    self.ContentType(content_type)
+    if content_type == self.ContentType.JSON.value:
+        rows = []
+        for item in self:
+            row = {}
+            for cell in item:
+                row[cell.name] = cell.content.dict()
+            rows.append(row)
+        return File(
+            name=f&#39;{self.name}.json&#39;,
+            content=json.dumps({&#39;data&#39;: rows}, default=str).encode(&#39;utf-8&#39;),
+            content_type=content_type,
+        )
+
+    api = SignalsNotebookApi.get_default_api()
+    log.debug(&#39;Get content for: %s| %s&#39;, self.__class__.__name__, self.eid)
+
+    response = api.call(
+        method=&#39;GET&#39;,
+        path=(self._get_endpoint(), self.eid, &#39;export&#39;),
+        params={
+            &#39;format&#39;: None,
+        },
+    )
+
+    content_disposition = response.headers.get(&#39;content-disposition&#39;, &#39;&#39;)
+    _, params = cgi.parse_header(content_disposition)
+
+    return File(
+        name=params[&#39;filename&#39;],
+        content=response.content,
+        content_type=response.headers.get(&#39;content-type&#39;),
+    )</code></pre>
+</details>
+</dd>
+<dt id="signals_notebook.entities.tables.table.Table.get_html"><code class="name flex">
+<span>def <span class="ident">get_html</span></span>(<span>self) ‑> str</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Get in HTML format</p>
+<h2 id="returns">Returns</h2>
+<p>Rendered template as a string</p></div>
 <details class="source">
 <summary>
 <span>Expand source code</span>
 </summary>
-<pre><code class="python">def get_content(self):
-    return super().get_content()</code></pre>
+<pre><code class="python">def get_html(self) -&gt; str:
+    &#34;&#34;&#34;Get in HTML format
+
+    Returns:
+        Rendered template as a string
+    &#34;&#34;&#34;
+
+    rows = []
+    column_definitions = self.get_column_definitions_list()
+
+    table_head = []
+    for column_definition in column_definitions:
+        table_head.append(column_definition.title)
+
+    for row in self:
+        reformatted_row = {}
+
+        for column_definition in column_definitions:
+            cell = cast(Row, row).get(column_definition.key, None)
+            cell = cast(Cell, cell)
+            reformatted_row[column_definition.title] = &#39;&#39; if cell is None else (cell.display or cell.value)
+
+        rows.append(reformatted_row)
+
+    template = env.get_template(self._template_name)
+    log.info(&#39;Html template for %s:%s has been rendered.&#39;, self.__class__.__name__, self.eid)
+
+    return template.render(name=self.name, table_head=table_head, rows=rows)</code></pre>
 </details>
 </dd>
 <dt id="signals_notebook.entities.tables.table.Table.save"><code class="name flex">
@@ -1127,19 +1950,15 @@ <h2 id="args">Args</h2>
 </dl>
 <h3>Inherited members</h3>
 <ul class="hlist">
-<li><code><b><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></b></code>:
+<li><code><b><a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></b></code>:
 <ul class="hlist">
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.load" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.load">load</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.refresh" href="../entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.set_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
-<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.short_description" href="../entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.get_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.get_template_name">get_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.refresh" href="../entity.html#signals_notebook.entities.entity.Entity.refresh">refresh</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.set_template_name" href="../entity.html#signals_notebook.entities.entity.Entity.set_template_name">set_template_name</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.short_description" href="../entity.html#signals_notebook.entities.entity.Entity.short_description">short_description</a></code></li>
 </ul>
 </li>
 </ul>
@@ -1179,6 +1998,41 @@ <h3>Class variables</h3>
 </dd>
 </dl>
 </dd>
+<dt id="signals_notebook.entities.tables.table.TableResponse"><code class="flex name class">
+<span>class <span class="ident">TableResponse</span></span>
+<span>(</span><span>**kwargs)</span>
+</code></dt>
+<dd>
+<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p>
+<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div>
+<details class="source">
+<summary>
+<span>Expand source code</span>
+</summary>
+<pre><code class="python">class TableResponse(Response[Table]):
+    pass</code></pre>
+</details>
+<h3>Ancestors</h3>
+<ul class="hlist">
+<li><a title="signals_notebook.entities.tables.table.Response[Table]" href="#signals_notebook.entities.tables.table.Response[Table]">Response[Table]</a></li>
+<li><a title="signals_notebook.common_types.Response" href="../../common_types.html#signals_notebook.common_types.Response">Response</a></li>
+<li>pydantic.generics.GenericModel</li>
+<li>pydantic.main.BaseModel</li>
+<li>pydantic.utils.Representation</li>
+<li>typing.Generic</li>
+</ul>
+<h3>Class variables</h3>
+<dl>
+<dt id="signals_notebook.entities.tables.table.TableResponse.data"><code class="name">var <span class="ident">data</span> : Union[pydantic.generics.ResponseData[<a title="signals_notebook.entities.tables.table.Table" href="#signals_notebook.entities.tables.table.Table">Table</a>], List[pydantic.generics.ResponseData[<a title="signals_notebook.entities.tables.table.Table" href="#signals_notebook.entities.tables.table.Table">Table</a>]]]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+<dt id="signals_notebook.entities.tables.table.TableResponse.links"><code class="name">var <span class="ident">links</span> : Optional[<a title="signals_notebook.common_types.Links" href="../../common_types.html#signals_notebook.common_types.Links">Links</a>]</code></dt>
+<dd>
+<div class="desc"></div>
+</dd>
+</dl>
+</dd>
 </dl>
 </section>
 </article>
@@ -1232,18 +2086,30 @@ <h4><code><a title="signals_notebook.entities.tables.table.Response[Row]" href="
 </ul>
 </li>
 <li>
+<h4><code><a title="signals_notebook.entities.tables.table.Response[Table]" href="#signals_notebook.entities.tables.table.Response[Table]">Response[Table]</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.tables.table.Response[Table].Config" href="#signals_notebook.entities.tables.table.Response[Table].Config">Config</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Response[Table].data" href="#signals_notebook.entities.tables.table.Response[Table].data">data</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Response[Table].links" href="#signals_notebook.entities.tables.table.Response[Table].links">links</a></code></li>
+</ul>
+</li>
+<li>
 <h4><code><a title="signals_notebook.entities.tables.table.Table" href="#signals_notebook.entities.tables.table.Table">Table</a></code></h4>
 <ul class="">
+<li><code><a title="signals_notebook.entities.tables.table.Table.ContentType" href="#signals_notebook.entities.tables.table.Table.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.add_row" href="#signals_notebook.entities.tables.table.Table.add_row">add_row</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.as_dataframe" href="#signals_notebook.entities.tables.table.Table.as_dataframe">as_dataframe</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.as_raw_data" href="#signals_notebook.entities.tables.table.Table.as_raw_data">as_raw_data</a></code></li>
-<li><code><a title="signals_notebook.entities.tables.table.Table.creation" href="#signals_notebook.entities.tables.table.Table.creation">creation</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Table.create" href="#signals_notebook.entities.tables.table.Table.create">create</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.delete_row_by_id" href="#signals_notebook.entities.tables.table.Table.delete_row_by_id">delete_row_by_id</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Table.dump" href="#signals_notebook.entities.tables.table.Table.dump">dump</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.dump_templates" href="#signals_notebook.entities.tables.table.Table.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.get" href="#signals_notebook.entities.tables.table.Table.get">get</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.get_column_definitions_list" href="#signals_notebook.entities.tables.table.Table.get_column_definitions_list">get_column_definitions_list</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.get_column_definitions_map" href="#signals_notebook.entities.tables.table.Table.get_column_definitions_map">get_column_definitions_map</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.get_content" href="#signals_notebook.entities.tables.table.Table.get_content">get_content</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Table.get_html" href="#signals_notebook.entities.tables.table.Table.get_html">get_html</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.Table.load" href="#signals_notebook.entities.tables.table.Table.load">load</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.save" href="#signals_notebook.entities.tables.table.Table.save">save</a></code></li>
 <li><code><a title="signals_notebook.entities.tables.table.Table.type" href="#signals_notebook.entities.tables.table.Table.type">type</a></code></li>
 </ul>
@@ -1255,6 +2121,13 @@ <h4><code><a title="signals_notebook.entities.tables.table.TableDataResponse" hr
 <li><code><a title="signals_notebook.entities.tables.table.TableDataResponse.links" href="#signals_notebook.entities.tables.table.TableDataResponse.links">links</a></code></li>
 </ul>
 </li>
+<li>
+<h4><code><a title="signals_notebook.entities.tables.table.TableResponse" href="#signals_notebook.entities.tables.table.TableResponse">TableResponse</a></code></h4>
+<ul class="">
+<li><code><a title="signals_notebook.entities.tables.table.TableResponse.data" href="#signals_notebook.entities.tables.table.TableResponse.data">data</a></code></li>
+<li><code><a title="signals_notebook.entities.tables.table.TableResponse.links" href="#signals_notebook.entities.tables.table.TableResponse.links">links</a></code></li>
+</ul>
+</li>
 </ul>
 </li>
 </ul>
diff --git a/docs/signals_notebook/entities/text.html b/docs/signals_notebook/entities/text.html
index 772f3560..797fcbbc 100644
--- a/docs/signals_notebook/entities/text.html
+++ b/docs/signals_notebook/entities/text.html
@@ -292,6 +292,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/todo_list/task.html b/docs/signals_notebook/entities/todo_list/task.html
index 8ff368f7..19e731ed 100644
--- a/docs/signals_notebook/entities/todo_list/task.html
+++ b/docs/signals_notebook/entities/todo_list/task.html
@@ -364,6 +364,7 @@ <h3>Inherited members</h3>
 <li><code><b><a title="signals_notebook.entities.entity.Entity" href="../entity.html#signals_notebook.entities.entity.Entity">Entity</a></b></code>:
 <ul class="hlist">
 <li><code><a title="signals_notebook.entities.entity.Entity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
+<li><code><a title="signals_notebook.entities.entity.Entity.dump_templates" href="../entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_html" href="../entity.html#signals_notebook.entities.entity.Entity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.entity.Entity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/todo_list/todo_list.html b/docs/signals_notebook/entities/todo_list/todo_list.html
index 039abc3a..0ebc2d11 100644
--- a/docs/signals_notebook/entities/todo_list/todo_list.html
+++ b/docs/signals_notebook/entities/todo_list/todo_list.html
@@ -313,6 +313,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="../entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="../entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="../contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="../entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="../entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/uploaded_resource.html b/docs/signals_notebook/entities/uploaded_resource.html
index 760c188c..89ce68a9 100644
--- a/docs/signals_notebook/entities/uploaded_resource.html
+++ b/docs/signals_notebook/entities/uploaded_resource.html
@@ -27,7 +27,8 @@ <h1 class="title">Module <code>signals_notebook.entities.uploaded_resource</code
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">import logging
-from typing import ClassVar, Literal, Optional
+from enum import Enum
+from typing import ClassVar, Literal
 
 from pydantic import Field
 
@@ -40,6 +41,9 @@ <h1 class="title">Module <code>signals_notebook.entities.uploaded_resource</code
 
 
 class UploadedResource(ContentfulEntity):
+    class ContentType(str, Enum):
+        BINARY = &#39;application/octet-stream&#39;
+
     type: Literal[EntityType.UPLOADED_RESOURCE] = Field(allow_mutation=False)
     _template_name: ClassVar = &#39;uploaded_resource.html&#39;
 
@@ -54,7 +58,7 @@ <h1 class="title">Module <code>signals_notebook.entities.uploaded_resource</code
         container: Container,
         name: str,
         content: bytes = b&#39;&#39;,
-        content_type: Optional[str] = None,
+        content_type: str = ContentType.BINARY,
         force: bool = True,
     ) -&gt; Entity:
         &#34;&#34;&#34;Create UploadedResource Entity
@@ -107,6 +111,9 @@ <h2 class="section-title" id="header-classes">Classes</h2>
 <span>Expand source code</span>
 </summary>
 <pre><code class="python">class UploadedResource(ContentfulEntity):
+    class ContentType(str, Enum):
+        BINARY = &#39;application/octet-stream&#39;
+
     type: Literal[EntityType.UPLOADED_RESOURCE] = Field(allow_mutation=False)
     _template_name: ClassVar = &#39;uploaded_resource.html&#39;
 
@@ -121,7 +128,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
         container: Container,
         name: str,
         content: bytes = b&#39;&#39;,
-        content_type: Optional[str] = None,
+        content_type: str = ContentType.BINARY,
         force: bool = True,
     ) -&gt; Entity:
         &#34;&#34;&#34;Create UploadedResource Entity
@@ -170,7 +177,7 @@ <h3>Class variables</h3>
 <h3>Static methods</h3>
 <dl>
 <dt id="signals_notebook.entities.uploaded_resource.UploadedResource.create"><code class="name flex">
-<span>def <span class="ident">create</span></span>(<span>*, container: <a title="signals_notebook.entities.container.Container" href="container.html#signals_notebook.entities.container.Container">Container</a>, name: str, content: bytes = b'', content_type: Optional[str] = None, force: bool = True) ‑> <a title="signals_notebook.entities.entity.Entity" href="entity.html#signals_notebook.entities.entity.Entity">Entity</a></span>
+<span>def <span class="ident">create</span></span>(<span>*, container: <a title="signals_notebook.entities.container.Container" href="container.html#signals_notebook.entities.container.Container">Container</a>, name: str, content: bytes = b'', content_type: str = ContentType.BINARY, force: bool = True) ‑> <a title="signals_notebook.entities.entity.Entity" href="entity.html#signals_notebook.entities.entity.Entity">Entity</a></span>
 </code></dt>
 <dd>
 <div class="desc"><p>Create UploadedResource Entity</p>
@@ -200,7 +207,7 @@ <h2 id="returns">Returns</h2>
     container: Container,
     name: str,
     content: bytes = b&#39;&#39;,
-    content_type: Optional[str] = None,
+    content_type: str = ContentType.BINARY,
     force: bool = True,
 ) -&gt; Entity:
     &#34;&#34;&#34;Create UploadedResource Entity
@@ -252,8 +259,10 @@ <h3>Inherited members</h3>
 <ul class="hlist">
 <li><code><b><a title="signals_notebook.entities.contentful_entity.ContentfulEntity" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity">ContentfulEntity</a></b></code>:
 <ul class="hlist">
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/entities/word.html b/docs/signals_notebook/entities/word.html
index 222b3106..4059402a 100644
--- a/docs/signals_notebook/entities/word.html
+++ b/docs/signals_notebook/entities/word.html
@@ -272,6 +272,7 @@ <h3>Inherited members</h3>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.ContentType">ContentType</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.delete" href="entity.html#signals_notebook.entities.entity.Entity.delete">delete</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.dump">dump</a></code></li>
+<li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.dump_templates" href="entity.html#signals_notebook.entities.entity.Entity.dump_templates">dump_templates</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_html" href="contentful_entity.html#signals_notebook.entities.contentful_entity.ContentfulEntity.get_html">get_html</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_list" href="entity.html#signals_notebook.entities.entity.Entity.get_list">get_list</a></code></li>
 <li><code><a title="signals_notebook.entities.contentful_entity.ContentfulEntity.get_subclasses" href="entity.html#signals_notebook.entities.entity.Entity.get_subclasses">get_subclasses</a></code></li>
diff --git a/docs/signals_notebook/materials/library.html b/docs/signals_notebook/materials/library.html
index c2e03f0b..be41ed61 100644
--- a/docs/signals_notebook/materials/library.html
+++ b/docs/signals_notebook/materials/library.html
@@ -467,13 +467,11 @@ <h1 class="title">Module <code>signals_notebook.materials.library</code></h1>
             name=params[&#39;filename&#39;], content=response.content, content_type=response.headers.get(&#39;content-type&#39;)
         )
 
-    def _is_import_job_completed(self, job_id: str) -&gt; bool:
+    def _get_import_job_completed_response(self, job_id: str) -&gt; requests.Response:
         api = SignalsNotebookApi.get_default_api()
         log.debug(&#39;Check job status for: %s| %s&#39;, self.__class__.__name__, self.eid)
 
-        response = api.call(method=&#39;GET&#39;, path=(self._get_endpoint(), &#39;bulkImport&#39;, &#39;jobs&#39;, job_id))
-
-        return response.status_code == 200 and response.json()[&#39;data&#39;][&#39;attributes&#39;][&#39;status&#39;] == &#39;COMPLETED&#39;
+        return api.call(method=&#39;GET&#39;, path=(self._get_endpoint(), &#39;bulkImport&#39;, &#39;jobs&#39;, job_id))
 
     def _import_materials(
         self,
@@ -552,15 +550,21 @@ <h1 class="title">Module <code>signals_notebook.materials.library</code></h1>
         initial_time = time.time()
 
         response = False
+        import_job_status = &#39;FAILED&#39;
 
         while time.time() - initial_time &lt; timeout:
-            if not self._is_import_job_completed(job_id):
+            completed_import_response = self._get_import_job_completed_response(job_id)
+            import_job_status = completed_import_response.json()[&#39;data&#39;][&#39;attributes&#39;][&#39;status&#39;]
+            import_response_code = completed_import_response.status_code
+
+            if import_response_code != 200 and import_job_status != &#39;COMPLETED&#39;:
                 time.sleep(period)
             else:
                 response = True
+                log.debug(&#39;Library import is completed&#39;)
                 break
 
-        if not response:
+        if not response and import_job_status == &#39;FAILED&#39;:
             log.debug(&#39;Time is over to import file&#39;)
 
             failure_report_reponse = api.call(
@@ -617,7 +621,9 @@ <h1 class="title">Module <code>signals_notebook.materials.library</code></h1>
 
         zip_buffer = self._generate_zip(materials)
 
-        self.bulk_import(File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;)</code></pre>
+        self.bulk_import(
+            File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;, timeout=120
+        )</code></pre>
 </details>
 </section>
 <section>
@@ -1303,13 +1309,11 @@ <h3>Class variables</h3>
             name=params[&#39;filename&#39;], content=response.content, content_type=response.headers.get(&#39;content-type&#39;)
         )
 
-    def _is_import_job_completed(self, job_id: str) -&gt; bool:
+    def _get_import_job_completed_response(self, job_id: str) -&gt; requests.Response:
         api = SignalsNotebookApi.get_default_api()
         log.debug(&#39;Check job status for: %s| %s&#39;, self.__class__.__name__, self.eid)
 
-        response = api.call(method=&#39;GET&#39;, path=(self._get_endpoint(), &#39;bulkImport&#39;, &#39;jobs&#39;, job_id))
-
-        return response.status_code == 200 and response.json()[&#39;data&#39;][&#39;attributes&#39;][&#39;status&#39;] == &#39;COMPLETED&#39;
+        return api.call(method=&#39;GET&#39;, path=(self._get_endpoint(), &#39;bulkImport&#39;, &#39;jobs&#39;, job_id))
 
     def _import_materials(
         self,
@@ -1388,15 +1392,21 @@ <h3>Class variables</h3>
         initial_time = time.time()
 
         response = False
+        import_job_status = &#39;FAILED&#39;
 
         while time.time() - initial_time &lt; timeout:
-            if not self._is_import_job_completed(job_id):
+            completed_import_response = self._get_import_job_completed_response(job_id)
+            import_job_status = completed_import_response.json()[&#39;data&#39;][&#39;attributes&#39;][&#39;status&#39;]
+            import_response_code = completed_import_response.status_code
+
+            if import_response_code != 200 and import_job_status != &#39;COMPLETED&#39;:
                 time.sleep(period)
             else:
                 response = True
+                log.debug(&#39;Library import is completed&#39;)
                 break
 
-        if not response:
+        if not response and import_job_status == &#39;FAILED&#39;:
             log.debug(&#39;Time is over to import file&#39;)
 
             failure_report_reponse = api.call(
@@ -1453,7 +1463,9 @@ <h3>Class variables</h3>
 
         zip_buffer = self._generate_zip(materials)
 
-        self.bulk_import(File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;)</code></pre>
+        self.bulk_import(
+            File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;, timeout=120
+        )</code></pre>
 </details>
 <h3>Ancestors</h3>
 <ul class="hlist">
@@ -1648,15 +1660,21 @@ <h2 id="returns">Returns</h2>
     initial_time = time.time()
 
     response = False
+    import_job_status = &#39;FAILED&#39;
 
     while time.time() - initial_time &lt; timeout:
-        if not self._is_import_job_completed(job_id):
+        completed_import_response = self._get_import_job_completed_response(job_id)
+        import_job_status = completed_import_response.json()[&#39;data&#39;][&#39;attributes&#39;][&#39;status&#39;]
+        import_response_code = completed_import_response.status_code
+
+        if import_response_code != 200 and import_job_status != &#39;COMPLETED&#39;:
             time.sleep(period)
         else:
             response = True
+            log.debug(&#39;Library import is completed&#39;)
             break
 
-    if not response:
+    if not response and import_job_status == &#39;FAILED&#39;:
         log.debug(&#39;Time is over to import file&#39;)
 
         failure_report_reponse = api.call(
@@ -1992,7 +2010,9 @@ <h2 id="returns">Returns</h2>
 
     zip_buffer = self._generate_zip(materials)
 
-    self.bulk_import(File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;)</code></pre>
+    self.bulk_import(
+        File(name=&#39;test&#39;, content=zip_buffer.getvalue(), content_type=&#39;zip&#39;), import_type=&#39;zip&#39;, timeout=120
+    )</code></pre>
 </details>
 </dd>
 </dl>
diff --git a/examples/Attributes.ipynb b/examples/Attributes.ipynb
index fd408781..35dd86d5 100644
--- a/examples/Attributes.ipynb
+++ b/examples/Attributes.ipynb
@@ -31,7 +31,7 @@
    "outputs": [
     {
      "data": {
-      "text/plain": "<signals_notebook.api.SignalsNotebookApi at 0x10e9ed550>"
+      "text/plain": "<signals_notebook.api.SignalsNotebookApi at 0x295a5f9c1f0>"
      },
      "execution_count": 2,
      "metadata": {},
@@ -48,7 +48,7 @@
    "execution_count": 3,
    "outputs": [],
    "source": [
-    "from signals_notebook.attributes.attribute import Attribute\n"
+    "from signals_notebook.attributes.attribute import Attribute"
    ],
    "metadata": {
     "collapsed": false,
@@ -63,7 +63,7 @@
    "outputs": [
     {
      "data": {
-      "text/plain": "Attribute(type='choice', id='attribute:8', name='GHS Signal Words', options=['WARNING', 'DANGER'])"
+      "text/plain": "Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:2', name='Date')"
      },
      "execution_count": 4,
      "metadata": {},
@@ -71,7 +71,7 @@
     }
    ],
    "source": [
-    "attribute = Attribute.get('attribute:8')\n",
+    "attribute = Attribute.get('attribute:2')\n",
     "attribute"
    ],
    "metadata": {
@@ -87,7 +87,7 @@
    "outputs": [
     {
      "data": {
-      "text/plain": "'WARNING'"
+      "text/plain": "['CURRENT_DATE']"
      },
      "execution_count": 5,
      "metadata": {},
@@ -95,7 +95,7 @@
     }
    ],
    "source": [
-    "attribute('WARNING')\n"
+    "attribute.options"
    ],
    "metadata": {
     "collapsed": false,
@@ -109,20 +109,312 @@
    "execution_count": 6,
    "outputs": [
     {
-     "ename": "ValueError",
-     "evalue": "Incorrect attribute value",
-     "output_type": "error",
-     "traceback": [
-      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
-      "\u001B[0;31mValueError\u001B[0m                                Traceback (most recent call last)",
-      "Input \u001B[0;32mIn [6]\u001B[0m, in \u001B[0;36m<module>\u001B[0;34m\u001B[0m\n\u001B[0;32m----> 1\u001B[0m \u001B[43mattribute\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mINCORRECT\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\n",
-      "File \u001B[0;32m~/PycharmProjects/pesn-python-sdk/src/signals_notebook/attributes/attribute.py:37\u001B[0m, in \u001B[0;36mAttribute.__call__\u001B[0;34m(self, value)\u001B[0m\n\u001B[1;32m     35\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21m__call__\u001B[39m(\u001B[38;5;28mself\u001B[39m, value: \u001B[38;5;28mstr\u001B[39m) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m \u001B[38;5;28mstr\u001B[39m:\n\u001B[1;32m     36\u001B[0m     \u001B[38;5;28;01mif\u001B[39;00m value \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39moptions:\n\u001B[0;32m---> 37\u001B[0m         \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mIncorrect attribute value\u001B[39m\u001B[38;5;124m'\u001B[39m)\n\u001B[1;32m     39\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m value\n",
-      "\u001B[0;31mValueError\u001B[0m: Incorrect attribute value"
-     ]
+     "data": {
+      "text/plain": "[Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:8', name='GHS Signal Words'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:10', name='Hazard Statements'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:11', name='GHS Hazards'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:14', name='Task Status'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:9', name='Precautionary Statements'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:4', name='Material Library Type'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:24', name='HPLC Sample Type'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:26', name='newAttribute'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:20', name='My List Attribute 1 (SK)'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:28', name='test'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:17', name='Inventory Container Library'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:16', name='Inventory Location Library'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:32', name='test1'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:21', name='My Ext List Attribute 1 (SK)'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:40', name='test2'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:41', name='test3'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:42', name='test37'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:25', name='Primer. Forward or Reverse'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:44', name='test327'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:23', name='HPLC Method'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:48', name='test32733'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:18', name='Inventory Security'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:19', name='My Number Sequence Attribute 1 (SK)'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:5', name='Product Id'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:6', name='Parallel Subexperiment Id'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:12', name='Sample Id'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:13', name='Task Id'),\n Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:15', name='Order Id')]"
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "attributes = Attribute.get_list()\n",
+    "all_attributes = list(attributes)\n",
+    "all_attributes"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "outputs": [],
+   "source": [
+    "# CREATION\n",
+    "new_attribute = Attribute.create(name='test3273', description='descriptions', options=['option'])"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:50', name='test3273')"
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option']"
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option', 'WARNING']"
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.add_option('WARNING')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option', 'IMPORTANT']"
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.update_option('WARNING', 'IMPORTANT')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option']"
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.delete_option('IMPORTANT')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "outputs": [],
+   "source": [
+    "new_attribute.delete()"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
     }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "outputs": [],
+   "source": [
+    "# CREATION\n",
+    "new_attribute = Attribute.create(name='test3273', description='descriptions', options=['option'])"
    ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "Attribute(type=<ObjectType.CHOICE: 'choice'>, id='attribute:51', name='test3273')"
+     },
+     "execution_count": 17,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option']"
+     },
+     "execution_count": 18,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option', 'WARNING']"
+     },
+     "execution_count": 19,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.add_option('WARNING')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option', 'IMPORTANT']"
+     },
+     "execution_count": 20,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.update_option('WARNING', 'IMPORTANT')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "['option']"
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "new_attribute.delete_option('IMPORTANT')\n",
+    "new_attribute.options"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "outputs": [],
    "source": [
-    "attribute('INCORRECT')"
+    "new_attribute.delete()"
    ],
    "metadata": {
     "collapsed": false,
diff --git a/examples/MaterialTable.ipynb b/examples/MaterialTable.ipynb
new file mode 100644
index 00000000..00020cb6
--- /dev/null
+++ b/examples/MaterialTable.ipynb
@@ -0,0 +1,117 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The dotenv extension is already loaded. To reload it, use:\n",
+      "  %reload_ext dotenv\n"
+     ]
+    }
+   ],
+   "source": [
+    "%load_ext dotenv\n",
+    "%dotenv\n",
+    "import os\n",
+    "\n",
+    "SN_API_HOST = os.getenv('SN_API_HOST')\n",
+    "SN_API_KEY = os.getenv('SN_API_KEY')"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "<signals_notebook.api.SignalsNotebookApi at 0x16b88974b50>"
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from signals_notebook.api import SignalsNotebookApi\n",
+    "\n",
+    "SignalsNotebookApi.init(SN_API_HOST, SN_API_KEY)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "outputs": [],
+   "source": [
+    "from signals_notebook.entities import EntityStore\n",
+    "\n",
+    "material_table = EntityStore.get(\"materialsTable:e8db5caa-15ce-4594-b09b-05e12209ac73\")"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "File(name='Materials.+Units.csv', content=b'ID,Unit Name,Custom Field 1 (SK)\\r\\nUNT-0001-0001,My unit 1 (SK),EQ-000007\\r\\n', content_type='text/csv')"
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "material_table.get_content()"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 2
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython2",
+   "version": "2.7.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
\ No newline at end of file
diff --git a/examples/PlateContainer.ipynb b/examples/PlateContainer.ipynb
new file mode 100644
index 00000000..39694f67
--- /dev/null
+++ b/examples/PlateContainer.ipynb
@@ -0,0 +1,219 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "outputs": [],
+   "source": [
+    "%load_ext dotenv\n",
+    "%dotenv\n",
+    "import os\n",
+    "\n",
+    "SN_API_HOST = os.getenv('SN_API_HOST')\n",
+    "SN_API_KEY = os.getenv('SN_API_KEY')"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "<signals_notebook.api.SignalsNotebookApi at 0x196681ea490>"
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from signals_notebook.api import SignalsNotebookApi\n",
+    "SignalsNotebookApi.init(SN_API_HOST, SN_API_KEY)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "outputs": [],
+   "source": [
+    "from signals_notebook.entities import EntityStore\n",
+    "\n",
+    "experiment = EntityStore.get(\"experiment:1cf65229-dea3-4bdb-b6c5-daf8565e39a0\")"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "outputs": [],
+   "source": [
+    "plate_container = list(experiment.get_children())[-1]"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "PlateContainer(type=<EntityType.PLATE_CONTAINER: 'plateContainer'>, eid='plateContainer:8728059f-8472-4872-929b-fa033e724fe3', digest='34718742', name='Plates-1', description='', created_at=datetime.datetime(2022, 7, 13, 9, 37, 5, 73000, tzinfo=datetime.timezone.utc), edited_at=datetime.datetime(2022, 7, 13, 9, 37, 29, 391000, tzinfo=datetime.timezone.utc))"
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plate_container"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "PlateRow(id=UUID('869491dc-bf8b-3c43-a225-629e2c10900a'), type=<ObjectType.PLATE_ROW: 'plateRow'>, cells=[PlateCell(id=UUID('76a7d17a-75b7-39a5-8549-05f073a064e3'), type=<ColumnDataType.TEXT: 'TEXT'>, name='Well ID', content=CellContent(user='A1', value='A1', values=None)), PlateCell(id=UUID('59f9b60c-a571-3c8e-982d-cdfe7e88e23c'), type=<ColumnDataType.TEXT: 'TEXT'>, name='Row', content=CellContent(user='A', value='A', values=None)), PlateCell(id=UUID('b5ff1ac8-310e-3848-9367-a4b8f4dc7ecc'), type=<ColumnDataType.INTEGER: 'INTEGER'>, name='Column', content=CellContent(user='1', value=1, values=None)), PlateCell(id=UUID('5a79aad4-7b07-39f1-9634-a2669a149a5b'), type=<ColumnDataType.TEXT: 'TEXT'>, name='Plate', content=CellContent(user='Plate-1', value='Plate-1', values=None)), PlateCell(id=UUID('43a9fcf2-bf40-3ed0-ba54-204275f053df'), type=<ColumnDataType.INTEGER: 'INTEGER'>, name='Order', content=CellContent(user='1', value=1, values=None)), PlateCell(id=UUID('f2053c2d-985d-3343-97e4-ae35b7fbe9d3'), type=<ColumnDataType.TEXT: 'TEXT'>, name='Plate ID', content=CellContent(user='d', value='d', values=None))])"
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plate_container[0]"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "PlateCell(id=UUID('76a7d17a-75b7-39a5-8549-05f073a064e3'), type=<ColumnDataType.TEXT: 'TEXT'>, name='Well ID', content=CellContent(user='A1', value='A1', values=None))"
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plate_container[0][0]"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "outputs": [],
+   "source": [
+    "experiment_html = experiment.get_html()"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "outputs": [
+    {
+     "data": {
+      "text/plain": "File(name='Plates-1', content=b'{\"eid\":\"plateContainer:8728059f-8472-4872-929b-fa033e724fe3\",\"name\":\"Plates-1\",\"numberOfRows\":32,\"numberOfColumns\":48,\"plates\":[{\"eid\":\"plate:f7cde4a2-f481-4c04-951f-83f59c45dd64\",\"name\":\"Plate-1\",\"plateCustomName\":\"d\",\"plateContainerEid\":\"plateContainer:8728059f-8472-4872-929b-fa033e724fe3\",\"isTemplate\":false,\"numberOfRows\":32,\"numberOfColumns\":48,\"annotationLayers\":{},\"fields\":[]},{\"eid\":\"plate:0b34fefd-71e4-4bbd-ba56-df2363e64877\",\"name\":\"Plate-2\",\"plateContainerEid\":\"plateContainer:8728059f-8472-4872-929b-fa033e724fe3\",\"isTemplate\":false,\"numberOfRows\":32,\"numberOfColumns\":48,\"annotationLayers\":{},\"fields\":[]}],\"annotationLayers\":[{\"id\":\"9c41b7eb-e684-4354-9386-2bf97ae961a5\",\"name\":\"Well Format\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"wellformat\",\"dataType\":\"TEXT\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":0,\"suggestions\":[]},{\"id\":\"b31bfe68-daa9-45e5-bda7-6f65733c792c\",\"name\":\"Concentration\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"concentration\",\"dataType\":\"DECIMAL\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":1,\"suggestions\":[]},{\"id\":\"212dfeb9-fa0d-49d5-927b-7c69054074a6\",\"name\":\"Material\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"material\",\"dataType\":\"LINK\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":2,\"suggestions\":[]},{\"id\":\"8dc52048-9c71-4442-b397-78bfdd164f4c\",\"name\":\"Amount\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"amount\",\"dataType\":\"DECIMAL\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":3,\"suggestions\":[]},{\"id\":\"e523e1dc-bb17-492e-8a9a-110060dfe561\",\"name\":\"Replicate\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"replicate\",\"dataType\":\"INTEGER\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":4,\"suggestions\":[]},{\"id\":\"24ea6db0-56ab-4542-9e1f-3b116915cd21\",\"name\":\"Deviation\",\"isPredefined\":true,\"isHidden\":false,\"annotationClass\":\"deviation\",\"dataType\":\"TEXT\",\"annotationLayerValues\":{},\"trashed\":false,\"order\":5,\"suggestions\":[]}],\"fields\":[]}', content_type='application/json; charset=utf-8')"
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "plate_container.get_content()"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "outputs": [],
+   "source": [
+    "with open('test_file.html', 'w') as f:\n",
+    "    f.write(experiment_html)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 2
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython2",
+   "version": "2.7.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
\ No newline at end of file
diff --git a/src/signals_notebook/attributes/attribute.py b/src/signals_notebook/attributes/attribute.py
index bb1d9633..d8f239df 100644
--- a/src/signals_notebook/attributes/attribute.py
+++ b/src/signals_notebook/attributes/attribute.py
@@ -1,22 +1,61 @@
 import logging
-from typing import cast, List, Literal
+from enum import Enum
+from typing import cast, Generator, Literal, Optional
 
 from pydantic import BaseModel
+from pydantic.fields import PrivateAttr
 
 from signals_notebook.api import SignalsNotebookApi
-from signals_notebook.common_types import AttrID, Response, ResponseData
+from signals_notebook.common_types import AttrID, ObjectType, Response, ResponseData
 
 log = logging.getLogger(__name__)
 
 
+class Action(str, Enum):
+    UPDATE = 'update'
+    DELETE = 'delete'
+    CREATE = 'create'
+
+
+class _Attributes(BaseModel):
+    action: Action
+    value: Optional[str]
+
+
+class _OptionRepresentation(BaseModel):
+    id: Optional[str]
+    type: Literal[ObjectType.ATTRIBUTE_OPTION] = ObjectType.ATTRIBUTE_OPTION
+    attributes: _Attributes
+
+
+class _AttributeOption(BaseModel):
+    value: str
+
+
+class _AttributeOptionResponse(Response[_AttributeOption]):
+    pass
+
+
 class Attribute(BaseModel):
-    type: Literal['choice']
+    type: str
     id: AttrID
     name: str
-    options: List[str]
+    _options: list[str] = PrivateAttr(default=[])
+
+    def __init__(self, *args, **kwargs):
+        self._options = kwargs.pop('options', [])
+        super().__init__(*args, **kwargs)
+        self.type = ObjectType.CHOICE
 
-    class Meta:
-        frozen = True
+    def __iter__(self):
+        if not self._options:
+            self._reload_options()
+        return self._options.__iter__()
+
+    def __len__(self) -> int:
+        if not self._options:
+            self._reload_options()
+        return len(self._options)
 
     @classmethod
     def _get_endpoint(cls) -> str:
@@ -39,14 +78,174 @@ def get(cls, id: AttrID) -> 'Attribute':
             path=(cls._get_endpoint(), id),
         )
 
-        result = Response[cls](**response.json())  # type: ignore
+        result = AttributeResponse(**response.json())
         log.debug('Get Attribute with ID: %s', id)
 
         return cast(ResponseData, result.data).body
 
-    def __call__(self, value: str) -> str:
-        if value not in self.options:
-            log.exception('Incorrect attribute value')
-            raise ValueError('Incorrect attribute value')
+    @classmethod
+    def get_list(cls) -> Generator['Attribute', None, None]:
+        """Get all Attributes.
+
+        Returns:
+           list of available Attributes
+        """
+        api = SignalsNotebookApi.get_default_api()
+        log.debug('Get List of Attributes')
+
+        response = api.call(
+            method='GET',
+            path=(cls._get_endpoint(),),
+        )
+        result = AttributeResponse(**response.json())
+
+        yield from [cast(ResponseData, item).body for item in result.data]
+
+        while result.links and result.links.next:
+            response = api.call(
+                method='GET',
+                path=result.links.next,
+            )
+
+            result = AttributeResponse(**response.json())
+            yield from [cast(ResponseData, item).body for item in result.data]
+
+        log.debug('List of Attributes was got successfully.')
+
+    @classmethod
+    def create(
+        cls,
+        name: str,
+        description: str,
+        options: list[str] = None,
+    ) -> 'Attribute':
+        """Create new Attribute
+
+        Args:
+            name: name of new Attribute
+            description: description of new Attribute
+            options: list of available id options for created Attribute
+
+        Returns:
+            Attribute
+        """
+        api = SignalsNotebookApi.get_default_api()
+
+        log.debug('Create Attribute: %s...', cls.__name__)
+
+        response = api.call(
+            method='POST',
+            path=(cls._get_endpoint(),),
+            json={
+                'data': {
+                    'type': ObjectType.ATTRIBUTE,
+                    'attributes': {
+                        'name': name,
+                        'type': ObjectType.CHOICE,
+                        'description': description,
+                        'options': options or [],
+                    },
+                }
+            },
+        )
+        log.debug('Attribute: %s was created.', cls.__name__)
+
+        result = AttributeResponse(**response.json())
+        return cast(ResponseData, result.data).body
+
+    def delete(self) -> None:
+        """Delete an Attribute by id.
+
+        Returns:
+
+        """
+        api = SignalsNotebookApi.get_default_api()
+        log.debug('Delete Attribute: %s...', self.id)
+
+        api.call(
+            method='DELETE',
+            path=(self._get_endpoint(), self.id),
+        )
+        log.debug('Attribute: %s was deleted successfully', self.id)
+
+    def add_option(self, option: str) -> None:
+        """Update option of Attribute by id.
+
+        Args:
+            option: option which will be added to option list in Attribute
+
+        Returns:
+
+        """
+        new_option = _OptionRepresentation(attributes=_Attributes(action=Action.CREATE, value=option))
+        log.debug('Creating Option: %s...', self.id)
+        self._patch_options(new_option)
+
+    def delete_option(self, option: str) -> None:
+        """Delete option of Attribute by id.
+
+        Args:
+            option: option which will be deleted from Attribute's option list
+
+        Returns:
+
+        """
+        deleted_option = _OptionRepresentation(id=option, attributes=_Attributes(action=Action.DELETE))
+        log.debug('Deleting Option: %s...', self.id)
+        self._patch_options(deleted_option)
+
+    def update_option(self, old_option: str, new_option: str) -> None:
+        """Update option of Attribute by id.
+
+        Args:
+            old_option: old option which will be updated
+            new_option: new option value
+
+        Returns:
+
+        """
+        option = _OptionRepresentation(id=old_option, attributes=_Attributes(action=Action.UPDATE, value=new_option))
+        log.debug('Patching Option: %s...', self.id)
+        self._patch_options(option)
+
+    def _patch_options(self, option: _OptionRepresentation) -> None:
+        api = SignalsNotebookApi.get_default_api()
+        api.call(
+            method='PATCH',
+            path=(self._get_endpoint(), self.id, 'options'),
+            json={'data': [option.dict(exclude_none=True)]},
+        )
+        self._reload_options()
+        log.debug('Attribute: %s was reloaded successfully', self.id)
+
+    def _reload_options(self):
+        self._options = []
+        api = SignalsNotebookApi.get_default_api()
+
+        response = api.call(
+            method='GET',
+            path=(self._get_endpoint(), self.id, 'options'),
+        )
+
+        result = _AttributeOptionResponse(**response.json())
+
+        for item in result.data:
+            body = cast(ResponseData, item).body
+            option = cast(_AttributeOption, body)
+
+            self._options.append(option.value)
+
+    @property
+    def options(self) -> list[str]:
+        """Get Attribute options
+
+        Returns:
+            list[str]
+        """
+        if not self._options:
+            self._reload_options()
+        return self._options
+
 
-        return value
+class AttributeResponse(Response[Attribute]):
+    pass
diff --git a/src/signals_notebook/common_types.py b/src/signals_notebook/common_types.py
index faf831c6..588c32c9 100644
--- a/src/signals_notebook/common_types.py
+++ b/src/signals_notebook/common_types.py
@@ -39,6 +39,9 @@ class ObjectType(str, Enum):
     PROFILE = 'profile'
     GROUP = 'group'
     ROLE = 'role'
+    PLATE_ROW = 'plateRow'
+    ATTRIBUTE_OPTION = 'option'
+    CHOICE = 'choice'
 
 
 class EntityType(str, Enum):
@@ -59,6 +62,8 @@ class EntityType(str, Enum):
     SPOTFIRE = 'spotfiredxp'
     TODO_LIST = 'linkedTaskContainer'
     TASK = 'task'
+    PLATE_CONTAINER = 'plateContainer'
+    MATERIAL_TABLE = 'materialsTable'
 
 
 class MaterialType(str, Enum):
diff --git a/src/signals_notebook/entities/__init__.py b/src/signals_notebook/entities/__init__.py
index 275c07e7..330d1949 100644
--- a/src/signals_notebook/entities/__init__.py
+++ b/src/signals_notebook/entities/__init__.py
@@ -17,3 +17,5 @@
 from signals_notebook.entities.power_point import PowerPoint  # noqa
 from signals_notebook.entities.spotfire import Spotfire  # noqa
 from signals_notebook.entities.uploaded_resource import UploadedResource  # noqa
+from signals_notebook.entities.plates.plate_container import PlateContainer  # noqa
+from signals_notebook.entities.materials_table import MaterialsTable  # noqa
diff --git a/src/signals_notebook/entities/materials_table.py b/src/signals_notebook/entities/materials_table.py
new file mode 100644
index 00000000..a1bdda72
--- /dev/null
+++ b/src/signals_notebook/entities/materials_table.py
@@ -0,0 +1,21 @@
+import logging
+from typing import ClassVar, Literal
+
+from pydantic import Field
+
+from signals_notebook.common_types import EntityType, File
+from signals_notebook.entities.contentful_entity import ContentfulEntity
+
+log = logging.getLogger(__name__)
+
+
+class MaterialsTable(ContentfulEntity):
+    type: Literal[EntityType.MATERIAL_TABLE] = Field(allow_mutation=False)
+    _template_name: ClassVar = 'materials_table.html'
+
+    @classmethod
+    def _get_entity_type(cls) -> EntityType:
+        return EntityType.MATERIAL_TABLE
+
+    def get_content(self) -> File:
+        return super()._get_content()
diff --git a/src/signals_notebook/entities/notebook.py b/src/signals_notebook/entities/notebook.py
index 83c10c3f..51343b4a 100644
--- a/src/signals_notebook/entities/notebook.py
+++ b/src/signals_notebook/entities/notebook.py
@@ -75,7 +75,7 @@ def dump(self, base_path: str, fs_handler: FSHandler) -> None:
             fs_handler.join_path(base_path, self.eid, 'metadata.json'),
             json.dumps({k: v for k, v in self.dict().items() if k in ('name', 'description', 'eid')}),
         )
-        for child in self.get_children():
+        for child in self.get_children(order=None):
             child.dump(base_path + '/' + self.eid, fs_handler)
 
     @classmethod
diff --git a/src/signals_notebook/entities/plates/__init__.py b/src/signals_notebook/entities/plates/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/signals_notebook/entities/plates/cell.py b/src/signals_notebook/entities/plates/cell.py
new file mode 100644
index 00000000..a6007c3e
--- /dev/null
+++ b/src/signals_notebook/entities/plates/cell.py
@@ -0,0 +1,43 @@
+from enum import Enum
+from typing import Generic, List, Optional, TypeVar
+from uuid import UUID
+
+from pydantic import Field
+from pydantic.generics import GenericModel
+
+
+CellContentType = TypeVar('CellContentType')
+
+
+class ColumnDataType(str, Enum):
+    NUMBER = 'NUMBER'
+    INTEGER = 'INTEGER'
+    DATE_TIME = 'DATETIME'
+    TEXT = 'TEXT'
+    LIST = 'LIST'
+    MULTI_SELECT = 'MULTI_SELECT'
+    ATTRIBUTE_LIST = 'ATTRIBUTE_LIST'
+    AUTOTEXT_LIST = 'AUTOTEXT_LIST'
+    BOOLEAN = 'BOOLEAN'
+    UNIT = 'UNIT'
+    LINK = 'LINK'
+    EXTERNAL_LINK = 'EXTERNAL_LINK'
+
+
+class CellContent(GenericModel, Generic[CellContentType]):
+    user: Optional[str]
+    value: Optional[CellContentType] = None
+    values: Optional[List[CellContentType]] = None
+
+    class Config:
+        validate_assignment = True
+
+
+class PlateCell(GenericModel, Generic[CellContentType]):
+    id: UUID = Field(allow_mutation=False, alias='key')
+    type: ColumnDataType = Field(allow_mutation=False)
+    name: str = Field(allow_mutation=False)
+    content: CellContent[CellContentType]
+
+    class Config:
+        validate_assignment = True
diff --git a/src/signals_notebook/entities/plates/plate_container.py b/src/signals_notebook/entities/plates/plate_container.py
new file mode 100644
index 00000000..1d03e2c1
--- /dev/null
+++ b/src/signals_notebook/entities/plates/plate_container.py
@@ -0,0 +1,93 @@
+import logging
+from typing import cast, ClassVar, Dict, List, Literal, Union
+from uuid import UUID
+
+from pydantic import Field, PrivateAttr
+
+from signals_notebook.api import SignalsNotebookApi
+from signals_notebook.common_types import EntityType, File, Response, ResponseData
+from signals_notebook.entities.contentful_entity import ContentfulEntity
+from signals_notebook.entities.plates.plate_row import PlateRow
+from signals_notebook.jinja_env import env
+
+log = logging.getLogger(__name__)
+
+
+class PlateContainerDataResponse(Response[PlateRow]):
+    pass
+
+
+class PlateContainer(ContentfulEntity):
+    type: Literal[EntityType.PLATE_CONTAINER] = Field(allow_mutation=False)
+    _rows: List[PlateRow] = PrivateAttr(default=[])
+    _rows_by_id: Dict[UUID, PlateRow] = PrivateAttr(default={})
+    _template_name: ClassVar = 'plate_container.html'
+
+    def __getitem__(self, index: Union[int, str, UUID]) -> PlateRow:
+        if not self._rows:
+            self._reload_data()
+
+        if isinstance(index, int):
+            return self._rows[index]
+
+        if isinstance(index, str):
+            return self._rows_by_id[UUID(index)]
+
+        if isinstance(index, UUID):
+            return self._rows_by_id[index]
+
+        raise IndexError('Invalid index')
+
+    def __iter__(self):
+        if not self._rows:
+            self._reload_data()
+
+        return self._rows.__iter__()
+
+    @classmethod
+    def _get_entity_type(cls) -> EntityType:
+        return EntityType.PLATE_CONTAINER
+
+    def _reload_data(self):
+        api = SignalsNotebookApi.get_default_api()
+        log.debug('Reloading rows for Plate Container: %s...', self.eid)
+
+        response = api.call(
+            method='GET',
+            path=('plates', self.eid, 'summary'),
+        )
+        result = PlateContainerDataResponse(**response.json())
+        self._rows = []
+        self._rows_by_id = {}
+        for item in result.data:
+            row = cast(PlateRow, cast(ResponseData, item).body)
+            assert row.id
+
+            self._rows.append(row)
+            self._rows_by_id[row.id] = row
+        log.debug('Data in Plate Container: %s were reloaded', self.eid)
+
+    def get_content(self) -> File:
+        """Get PlateContainer content
+
+        Returns:
+            File
+        """
+        return super()._get_content()
+
+    def get_html(self) -> str:
+        """Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        """
+        if not self._rows:
+            self._reload_data()
+        table_head = None
+        if self._rows:
+            table_head = self._rows[0]
+
+        template = env.get_template(self._template_name)
+        log.info('Html template for %s:%s has been rendered.', self.__class__.__name__, self.eid)
+
+        return template.render(name=self.name, table_head=table_head, rows=self._rows)
diff --git a/src/signals_notebook/entities/plates/plate_row.py b/src/signals_notebook/entities/plates/plate_row.py
new file mode 100644
index 00000000..91a98659
--- /dev/null
+++ b/src/signals_notebook/entities/plates/plate_row.py
@@ -0,0 +1,49 @@
+import logging
+from typing import Dict, List, Literal, Optional, Union
+from uuid import UUID
+
+from pydantic import BaseModel, Field, PrivateAttr
+
+from signals_notebook.common_types import ObjectType
+from signals_notebook.entities.plates.cell import PlateCell
+
+log = logging.getLogger(__name__)
+
+
+class PlateRow(BaseModel):
+    id: Optional[UUID] = Field(allow_mutation=False, default=None)
+    type: Literal[ObjectType.PLATE_ROW] = Field(allow_mutation=False, default=ObjectType.ADT_ROW)
+    cells: List[PlateCell]
+    _cells_dict: Dict[Union[UUID, str], PlateCell] = PrivateAttr(default={})
+
+    def __init__(self, **data):
+        super().__init__(**data)
+
+        for cell in self.cells:
+            self._cells_dict[cell.id] = cell
+            self._cells_dict[cell.name] = cell
+
+    class Config:
+        validate_assignment = True
+
+    def __getitem__(self, index: Union[int, str, UUID]) -> PlateCell:
+        if isinstance(index, int):
+            return self.cells[index]
+
+        if isinstance(index, str):
+            if index in self._cells_dict:
+                return self._cells_dict[index]
+
+            try:
+                if UUID(index) in self._cells_dict:
+                    return self._cells_dict[UUID(index)]
+            except ValueError:
+                pass
+
+        if isinstance(index, UUID):
+            return self._cells_dict[index]
+
+        raise IndexError('Invalid index')
+
+    def __iter__(self):
+        return self.cells.__iter__()
diff --git a/src/signals_notebook/entities/samples/cell.py b/src/signals_notebook/entities/samples/cell.py
index 281b9e9e..2e164130 100644
--- a/src/signals_notebook/entities/samples/cell.py
+++ b/src/signals_notebook/entities/samples/cell.py
@@ -17,19 +17,48 @@ class SampleCellContent(GenericModel, Generic[CellValueType]):
     _changed: bool = PrivateAttr(default=False)
 
     def set_value(self, new_value: CellValueType) -> None:
+        """Set new value
+
+        Args:
+            new_value: new value for value field
+
+        Returns:
+
+        """
         self.value = new_value
         self._changed = True
 
     def set_values(self, new_values: List[CellValueType]) -> None:
+        """Set new values
+
+        Args:
+            new_values: new list of values for values field
+
+        Returns:
+
+        """
         self.values = new_values
         self._changed = True
 
     def set_name(self, new_name: str) -> None:
+        """Set new name
+
+        Args:
+            new_name: new name for name field
+
+        Returns:
+
+        """
         self.name = new_name
         self._changed = True
 
     @property
     def is_changed(self) -> bool:
+        """Get is_changed value
+
+        Returns:
+            bool: True/False
+        """
         return self._changed
 
 
@@ -49,30 +78,79 @@ class SampleCell(BaseModel):
     content: SampleCellContent = Field(default=SampleCellContent())
 
     def set_content_value(self, new_value: CellValueType) -> None:
+        """Set new content value
+
+        Args:
+            new_value: new value of SampleCellContent value field
+
+        Returns:
+
+        """
         self.content.set_value(new_value)
 
     def set_content_values(self, new_values: List[CellValueType]) -> None:
+        """Set new content values
+
+        Args:
+            new_values: new list of values of SampleCellContent values field
+
+        Returns:
+
+        """
         self.content.set_values(new_values)
 
     def set_content_name(self, new_name: str) -> None:
+        """Set new content name
+
+        Args:
+            new_name: new name of SampleCellContent name field
+
+        Returns:
+
+        """
         self.content.set_name(new_name)
 
     @property
     def content_value(self) -> Optional[CellValueType]:
+        """Get content value
+
+        Returns:
+            Optional[CellValueType]
+        """
         return self.content.value
 
     @property
     def content_values(self) -> Optional[List[CellValueType]]:
+        """Get content values
+
+        Returns:
+            Optional[List[CellValueType]]
+        """
         return self.content.values
 
     @property
     def content_name(self) -> Optional[str]:
+        """Get content name
+
+        Returns:
+            Optional[str]
+        """
         return self.content.name
 
     @property
     def is_changed(self) -> bool:
+        """Checking if SampleCell has been modified
+
+        Returns:
+            bool
+        """
         return False if self.content is None else self.content.is_changed
 
     @property
     def representation_for_update(self) -> SampleCellBody:
+        """Get representation of body for update
+
+        Returns:
+            SampleCellBody
+        """
         return SampleCellBody(id=str(self.id), attributes=Content(content=self.content))
diff --git a/src/signals_notebook/entities/samples/sample.py b/src/signals_notebook/entities/samples/sample.py
index 2dae4141..53d8f2a3 100644
--- a/src/signals_notebook/entities/samples/sample.py
+++ b/src/signals_notebook/entities/samples/sample.py
@@ -1,4 +1,5 @@
 import json
+import logging
 from typing import cast, Dict, List, Literal, Optional, TYPE_CHECKING, Union
 from uuid import UUID
 
@@ -20,6 +21,8 @@
 if TYPE_CHECKING:
     from signals_notebook.entities import SamplesContainer
 
+log = logging.getLogger(__name__)
+
 
 class _SampleAttributes(BaseModel):
     fields: Optional[List[SampleCell]] = []
@@ -81,6 +84,7 @@ def _get_samples_endpoint(cls) -> str:
         return 'samples'
 
     def _reload_cells(self) -> None:
+        log.debug('Reloading cells for Sample: %s...', self.eid)
         self._cells = []
         self._cells_by_id = {}
 
@@ -101,8 +105,18 @@ def _reload_cells(self) -> None:
 
             self._cells.append(sample_cell)
             self._cells_by_id[sample_cell.id] = sample_cell
+        log.debug('Cells for Sample: %s were reloaded', self.eid)
 
     def save(self, force: bool = True) -> None:
+        """Save Sample.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        """
+        log.debug('Saving Sample: %s...', self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         request_body = []
@@ -125,6 +139,7 @@ def save(self, force: bool = True) -> None:
             },
         )
         self._reload_cells()
+        log.debug('Sample: %s were saved successfully.', self.eid)
 
     @classmethod
     def create(
@@ -136,6 +151,22 @@ def create(
         digest: str = None,
         force: bool = True,
     ) -> 'Sample':
+        """Create Sample Entity
+
+        Args:
+            cells: Sample's data
+            template: template for Sample creation
+            ancestors: Container or SamplesContainer where create new Sample
+            digest: Indicate digest of entity. It is used to avoid conflict while concurrent editing.
+                If the parameter 'force' is true, this parameter is optional.
+                If the parameter 'force' is false, this parameter is required.
+            force: Force to create without doing digest check
+
+        Returns:
+            Sample
+        """
+        log.debug('Create Sample: %s ', cls.__name__)
+
         relationships = None
         if template or ancestors:
             relationships = _SampleRelationships(
diff --git a/src/signals_notebook/entities/samples/samples_container.py b/src/signals_notebook/entities/samples/samples_container.py
index b90a9f7e..dd0ee79a 100644
--- a/src/signals_notebook/entities/samples/samples_container.py
+++ b/src/signals_notebook/entities/samples/samples_container.py
@@ -1,4 +1,5 @@
 import csv
+import logging
 from io import StringIO
 from typing import cast, ClassVar, Dict, Generator, List, Literal, Union
 from uuid import UUID
@@ -11,6 +12,8 @@
 from signals_notebook.entities.contentful_entity import ContentfulEntity
 from signals_notebook.jinja_env import env
 
+log = logging.getLogger(__name__)
+
 
 class SamplesContainerResponse(Response[Sample]):
     pass
@@ -47,9 +50,16 @@ def _get_entity_type(cls) -> EntityType:
         return EntityType.SAMPLES_CONTAINER
 
     def get_content(self) -> File:
+        """Get SamplesContainer content
+
+        Returns:
+            File
+        """
         return super()._get_content()
 
     def _reload_samples(self) -> None:
+        log.debug('Reloading samples for Samples Container: %s...', self.eid)
+
         self._samples = []
         self._samples_by_id = {}
         for item in self._get_samples():
@@ -58,8 +68,10 @@ def _reload_samples(self) -> None:
 
             self._samples.append(item)
             self._samples_by_id[sample.eid] = sample
+        log.debug('Data in Samples Container: %s were reloaded', self.eid)
 
     def _get_samples(self) -> Generator[Sample, None, None]:
+        log.debug('Getting samples for Samples Container: %s...', self.eid)
         api = SignalsNotebookApi.get_default_api()
 
         response = api.call(
@@ -79,17 +91,35 @@ def _get_samples(self) -> Generator[Sample, None, None]:
 
             result = SamplesContainerResponse(**response.json())
             yield from [cast(ResponseData, item).body for item in result.data]
+        log.debug('Samples for SamplesContainer: %s were got successfully.', self.eid)
 
     def save(self, force: bool = True) -> None:
+        """Save SamplesContainer content.
+
+        Args:
+            force: Force to update content without doing digest check.
+
+        Returns:
+
+        """
+        log.debug('Saving SamplesContainer: %s...', self.eid)
         for item in self._samples:
             item.save(force=force)
         self._reload_samples()
+        log.debug('SamplesContainer: %s were saved successfully.', self.eid)
 
     def get_html(self) -> str:
+        """Get in HTML format
+
+        Returns:
+            Rendered HTML in string format
+        """
         file = self.get_content()
         content = StringIO(file.content.decode('utf-8'))
         csv_data = list(csv.reader(content))
         table_head = csv_data[0]
         rows = csv_data[1:]
         template = env.get_template(self._template_name)
+        log.info('Html template for %s:%s has been rendered.', self.__class__.__name__, self.eid)
+
         return template.render(name=self.name, table_head=table_head, rows=rows)
diff --git a/src/signals_notebook/entities/stoichiometry/data_grid.py b/src/signals_notebook/entities/stoichiometry/data_grid.py
index a4d3792e..76d6f239 100644
--- a/src/signals_notebook/entities/stoichiometry/data_grid.py
+++ b/src/signals_notebook/entities/stoichiometry/data_grid.py
@@ -73,7 +73,6 @@ def __getitem__(self, index: Union[int, str, UUID]) -> RowClass:
         if isinstance(index, UUID):
             return self._rows_by_id[index]
 
-        log.exception('IndexError were caught. Invalid index')
         raise IndexError('Invalid index')
 
     @property
diff --git a/src/signals_notebook/entities/tables/row.py b/src/signals_notebook/entities/tables/row.py
index 5216827d..87762e7d 100644
--- a/src/signals_notebook/entities/tables/row.py
+++ b/src/signals_notebook/entities/tables/row.py
@@ -151,7 +151,6 @@ def __getitem__(self, index: Union[int, str, UUID]) -> GenericCell:
         if isinstance(index, UUID):
             return self._cells_dict[index]
 
-        log.exception('IndexError were caught. Invalid index')
         raise IndexError('Invalid index')
 
     def __iter__(self):
diff --git a/src/signals_notebook/templates/materials_table.html b/src/signals_notebook/templates/materials_table.html
new file mode 100644
index 00000000..d24159bd
--- /dev/null
+++ b/src/signals_notebook/templates/materials_table.html
@@ -0,0 +1,10 @@
+<div style="margin: 10px 10px; padding: 6px 10px; border: solid 1px #f5f5f5;">
+    <h2>{{ data['name'] }}</h2>
+    {% if data['content'] %}
+    {% if data['name'].endswith('.csv') %}
+    <a href="{{ data['content'] }}" download="{{ data['name'] }}">DOWNLOAD .CSV FILE</a>
+    {% else %}
+    <a href="{{ data['content'] }}" download="{{ data['name'] }}.csv">DOWNLOAD .CSV FILE</a>
+    {% endif %}
+    {% endif %}
+</div>
\ No newline at end of file
diff --git a/src/signals_notebook/templates/plate_container.html b/src/signals_notebook/templates/plate_container.html
new file mode 100644
index 00000000..bc42f6ce
--- /dev/null
+++ b/src/signals_notebook/templates/plate_container.html
@@ -0,0 +1,29 @@
+{% if rows %}
+<div class="table-wrapper" style="margin: 10px 10px; padding: 6px 10px; border: solid 1px #f5f5f5;">
+    <div class="table-scroll">
+        <h2>{{ name }}</h2>
+        <table>
+            <thead>
+                <tr>
+                {% for cell in table_head %}
+                    <th>{{ cell.name | safe }}</th>
+                {% endfor %}
+                </tr>
+            </thead>
+            <tbody>
+                {% for row in rows %}
+                <tr>
+                    {% for value in row %}
+                        {% if value.content.value == None %}
+                            <td></td>
+                        {% else %}
+                            <td>{{ value.content.value | safe }}</td>
+                        {% endif %}
+                    {% endfor %}
+                </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+</div>
+{% endif %}
\ No newline at end of file


Test patch:
diff --git a/tests/attributes/conftest.py b/tests/attributes/conftest.py
index e640445e..2e79245e 100644
--- a/tests/attributes/conftest.py
+++ b/tests/attributes/conftest.py
@@ -1,6 +1,17 @@
+import pytest
 from pytest_factoryboy import register
 
 from tests.attributes.factories import AttributeFactory, AttrIDFactory
 
 register(AttrIDFactory)
 register(AttributeFactory)
+
+
+@pytest.fixture()
+def get_response_object(mocker):
+    def _f(response):
+        mock = mocker.Mock()
+        mock.json.return_value = response
+        return mock
+
+    return _f
diff --git a/tests/attributes/test_attribute.py b/tests/attributes/test_attribute.py
index 8facb0bb..8e9446f8 100644
--- a/tests/attributes/test_attribute.py
+++ b/tests/attributes/test_attribute.py
@@ -1,29 +1,153 @@
 import pytest
 
 from signals_notebook.attributes import Attribute
+from signals_notebook.attributes.attribute import Action
+from signals_notebook.common_types import AttrID, ObjectType
 
 
-def test_get(attr_id_factory, api_mock):
-    _id = attr_id_factory()
+@pytest.fixture()
+def attribute_response():
+    def wrapper(_id: AttrID):
+        return {
+            'links': {'self': f'https://example.com/api/rest/v1.0/attributes/{_id}'},
+            'data': {
+                'type': 'attribute',
+                'id': _id,
+                'links': {'self': f'https://example.com/api/rest/v1.0/attributes/{_id}'},
+                'attributes': {
+                    'id': _id,
+                    'name': 'GHS Signal Words',
+                    'type': 'choice',
+                    'options': ['WARNING', 'DANGER'],
+                    'counts': {'total': 2, 'templates': {'total': 0, 'system': 0}},
+                },
+            },
+        }
 
-    response = {
-        'links': {'self': f'https://quantori.signalsnotebook.perkinelmer.cloud/api/rest/v1.0/attributes/{id}'},
-        'data': {
-            'type': 'attribute',
-            'id': _id,
-            'links': {
-                'self': f'https://quantori.signalsnotebook.perkinelmer.cloud/api/rest/v1.0/attributes/{id}'
+    return wrapper
+
+
+@pytest.fixture()
+def attributes_response():
+    return {
+        'data': [
+            {
+                'type': 'entity',
+                'id': 'attribute:18',
+                'links': {'self': 'https://example.com/api/rest/v1.0/entities/attribute:18'},
+                'attributes': {
+                    'id': 'attribute:18',
+                    'eid': 'attribute:18',
+                    'name': 'Inventory Security',
+                    'type': 'attribute',
+                    'digest': '0',
+                    'fields': {},
+                    'flags': {'canEdit': True},
+                },
             },
-            'attributes': {
-                'id': _id,
-                'name': 'GHS Signal Words',
-                'type': 'choice',
-                'options': ['WARNING', 'DANGER'],
-                'counts': {'total': 2, 'templates': {'total': 0, 'system': 0}},
+            {
+                'type': 'entity',
+                'id': 'attribute:4',
+                'links': {'self': 'https://example.com/api/rest/v1.0/entities/attribute:4'},
+                'attributes': {
+                    'id': 'attribute:4',
+                    'eid': 'attribute:4',
+                    'name': 'Material Library Type',
+                    'type': 'attribute',
+                    'digest': '0',
+                    'fields': {},
+                },
+            },
+            {
+                'type': 'entity',
+                'id': 'attribute:26',
+                'links': {'self': 'https://example.com/api/rest/v1.0/entities/attribute:26'},
+                'attributes': {
+                    'id': 'attribute:26',
+                    'eid': 'attribute:26',
+                    'name': 'newAttribute',
+                    'description': 'Test',
+                    'type': 'attribute',
+                    'digest': '0',
+                    'fields': {},
+                    'flags': {'canEdit': True},
+                },
             },
+        ]
+    }
+
+
+@pytest.fixture()
+def options_response():
+    return {
+        'links': {
+            'self': 'https://example.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+            'first': 'https://example.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
         },
+        'data': [
+            {'type': 'option', 'id': 'ladflklsjdf', 'attributes': {'key': 'ladflklsjdf', 'value': 'ladflklsjdf'}},
+            {'type': 'option', 'id': 'option2', 'attributes': {'key': 'option2', 'value': 'option2'}},
+            {'type': 'option', 'id': 'option3', 'attributes': {'key': 'option3', 'value': 'option3'}},
+        ],
     }
 
+
+@pytest.fixture()
+def options_response_for_update():
+    def wrapper(value: str):
+        return {
+            'links': {
+                'self': 'https://ex.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+                'first': 'https://ex.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+            },
+            'data': [
+                {'type': 'option', 'id': 'ladflklsjdf', 'attributes': {'key': 'ladflklsjdf', 'value': 'ladflklsjdf'}},
+                {'type': 'option', 'id': 'option2', 'attributes': {'key': 'option2', 'value': value}},
+                {'type': 'option', 'id': 'option3', 'attributes': {'key': 'option3', 'value': 'option3'}},
+            ],
+        }
+
+    return wrapper
+
+
+@pytest.fixture()
+def options_response_for_delete():
+    return {
+        'links': {
+            'self': 'https://example.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+            'first': 'https://example.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+        },
+        'data': [
+            {'type': 'option', 'id': 'ladflklsjdf', 'attributes': {'key': 'ladflklsjdf', 'value': 'ladflklsjdf'}},
+            {'type': 'option', 'id': 'option3', 'attributes': {'key': 'option3', 'value': 'option3'}},
+        ],
+    }
+
+
+@pytest.fixture()
+def options_response_for_create():
+    def wrapper(value: str):
+        return {
+            'links': {
+                'self': 'https://ex.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+                'first': 'https://ex.com/api/rest/v1.0/attributes/attribute:18/options?page[offset]=0&page[limit]=20',
+            },
+            'data': [
+                {'type': 'option', 'id': 'ladflklsjdf', 'attributes': {'key': 'ladflklsjdf', 'value': 'ladflklsjdf'}},
+                {'type': 'option', 'id': 'option2', 'attributes': {'key': 'option2', 'value': 'option2'}},
+                {'type': 'option', 'id': 'option3', 'attributes': {'key': 'option3', 'value': 'option3'}},
+                {'type': 'option', 'id': value, 'attributes': {'key': value, 'value': value}},
+            ],
+        }
+
+    return wrapper
+
+
+def test_get(attr_id_factory, api_mock, attribute_response):
+    _id = attr_id_factory()
+
+    response = attribute_response(_id)
+
     api_mock.call.return_value.json.return_value = response
 
     result = Attribute.get(_id)
@@ -31,22 +155,230 @@ def test_get(attr_id_factory, api_mock):
     api_mock.call.assert_called_once_with(method='GET', path=('attributes', _id))
 
     assert isinstance(result, Attribute)
-    assert result.type == 'choice'
+    assert result.type == ObjectType.CHOICE
     assert result.name == response['data']['attributes']['name']
     assert result.id == _id
-    assert result.options == response['data']['attributes']['options']
 
 
-def test_check_correct_value(attribute_factory):
-    attribute = attribute_factory(name='test')
+def test_get_list(api_mock, attributes_response):
+    api_mock.call.return_value.json.return_value = attributes_response
+
+    attributes = Attribute.get_list()
+
+    for item in attributes:
+        assert isinstance(item, Attribute)
+
+    api_mock.call.assert_called_once_with(method='GET', path=('attributes',))
+
+
+def test_create(api_mock, attr_id_factory, attribute_response):
+    _id = attr_id_factory()
+    option_id = 'HEY'
+    response = attribute_response(_id)
+    api_mock.call.return_value.json.return_value = response
+
+    name = 'test327'
+    description = 'descriptions'
+    new_attribute = Attribute.create(name=name, description=description, options=[option_id])
+
+    api_mock.call.assert_called_once_with(
+        method='POST',
+        path=('attributes',),
+        json={
+            'data': {
+                'type': ObjectType.ATTRIBUTE,
+                'attributes': {
+                    'name': name,
+                    'type': ObjectType.CHOICE,
+                    'description': description,
+                    'options': [option_id],
+                },
+            }
+        },
+    )
+
+    assert isinstance(new_attribute, Attribute)
+    assert new_attribute.type == ObjectType.CHOICE
+    assert new_attribute.name == response['data']['attributes']['name']
+    assert new_attribute.id == _id
+
+
+def test_add_option(
+    api_mock,
+    options_response,
+    attribute_factory,
+    get_response_object,
+    options_response_for_create,
+    mocker,
+):
+    attribute = attribute_factory()
+    option = 'GOGOGOGOGO'
+
+    assert attribute._options == []
+
+    api_mock.call.return_value.json.return_value = options_response
+    _ = attribute.options
+
+    assert attribute._options != []
+
+    create_response = options_response_for_create(option)
+    api_mock.call.side_effect = [get_response_object(create_response), get_response_object(create_response)]
+    attribute.add_option(option=option)
+
+    api_mock.call.return_value.json.return_value = create_response
+    assert len(attribute) == 4
+
+    api_mock.call.assert_has_calls(
+        [
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+            mocker.call(
+                method='PATCH',
+                path=('attributes', attribute.id, 'options'),
+                json={
+                    'data': [
+                        {
+                            'type': ObjectType.ATTRIBUTE_OPTION,
+                            'attributes': {'action': Action.CREATE, 'value': option},
+                        }
+                    ]
+                },
+            ),
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+        ],
+        any_order=True,
+    )
+
+
+def test_delete_option(
+    api_mock, options_response, attribute_factory, get_response_object, options_response_for_delete, mocker
+):
+    attribute = attribute_factory()
+    option = 'option2'
+
+    assert attribute._options == []
+
+    api_mock.call.return_value.json.return_value = options_response
+    _ = attribute.options
+
+    assert attribute._options != []
+
+    delete_response = options_response_for_delete
+    api_mock.call.side_effect = [get_response_object(delete_response), get_response_object(delete_response)]
+    attribute.delete_option(option=option)
+
+    assert len(attribute) == 2
+    api_mock.call.assert_has_calls(
+        [
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+            mocker.call(
+                method='PATCH',
+                path=('attributes', attribute.id, 'options'),
+                json={
+                    'data': [
+                        {
+                            'id': option,
+                            'type': ObjectType.ATTRIBUTE_OPTION,
+                            'attributes': {'action': Action.DELETE},
+                        }
+                    ]
+                },
+            ),
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+        ],
+        any_order=True,
+    )
+
+
+def test_update_option(
+    api_mock, options_response, attribute_factory, get_response_object, options_response_for_update, mocker
+):
+    attribute = attribute_factory()
+    old_option = 'option2'
+    new_option = 'GOGOGOGOGO'
+
+    assert attribute._options == []
+
+    api_mock.call.return_value.json.return_value = options_response
+    _ = attribute.options
+
+    assert len(attribute) == 3
+    assert attribute._options != []
+
+    update_response = options_response_for_update(old_option)
+    api_mock.call.side_effect = [get_response_object(update_response), get_response_object(update_response)]
+    attribute.update_option(old_option=old_option, new_option=new_option)
+
+    assert len(attribute) == 3
+    api_mock.call.assert_has_calls(
+        [
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+            mocker.call(
+                method='PATCH',
+                path=('attributes', attribute.id, 'options'),
+                json={
+                    'data': [
+                        {
+                            'id': old_option,
+                            'type': ObjectType.ATTRIBUTE_OPTION,
+                            'attributes': {'action': Action.UPDATE, 'value': new_option},
+                        }
+                    ]
+                },
+            ),
+            mocker.call(method='GET', path=('attributes', attribute.id, 'options')),
+        ],
+        any_order=True,
+    )
+
+
+def test_delete(api_mock, attr_id_factory, attribute_factory):
+    _id = attr_id_factory()
+    attribute = attribute_factory(id=_id)
+
+    api_mock.call.return_value.json.return_value = ''
+
+    attribute.delete()
+
+    api_mock.call.assert_called_once_with(method='DELETE', path=('attributes', _id))
+
+
+def test_reload_options(api_mock, options_response, attribute_factory):
+    attribute = attribute_factory()
+
+    assert attribute._options == []
+
+    api_mock.call.return_value.json.return_value = options_response
+    options = attribute.options
+
+    assert attribute._options != []
+
+    for item in options:
+        assert isinstance(item, str)
+
+
+def test_iter(api_mock, options_response, attribute_factory):
+    attribute = attribute_factory()
+
+    assert attribute._options == []
+
+    api_mock.call.return_value.json.return_value = options_response
+
+    for item in attribute:
+        assert isinstance(item, str)
+
+    assert attribute._options != []
+
+
+def test_len(api_mock, options_response, attribute_factory):
+    attribute = attribute_factory()
 
-    assert attribute('test 1') == 'test 1'
+    assert attribute._options == []
 
+    api_mock.call.return_value.json.return_value = options_response
 
-def test_check_incorrect_value(attribute_factory):
-    attribute = attribute_factory(name='test')
+    assert len(attribute) == 3
 
-    with pytest.raises(ValueError) as e:
-        attribute('test 10')
+    for item in attribute:
+        assert isinstance(item, str)
 
-    assert str(e.value) == 'Incorrect attribute value'
+    assert attribute._options != []
diff --git a/tests/entities/conftest.py b/tests/entities/conftest.py
index 7f333680..20713ae4 100644
--- a/tests/entities/conftest.py
+++ b/tests/entities/conftest.py
@@ -9,6 +9,7 @@
     ExcelFactory,
     ExperimentFactory,
     ImageFactory,
+    MaterialTableFactory,
     NotebookFactory,
     PowerPointFactory,
     SpotfireFactory,
@@ -16,6 +17,7 @@
     UploadedResourceFactory,
     WordFactory,
 )
+from tests.entities.plates.factories import PlateContainerFactory
 from tests.entities.samples.factories import (
     SampleCellFactory,
     SampleFactory,
@@ -47,6 +49,8 @@
 register(TaskFactory)
 register(TaskCellFactory)
 register(UploadedResourceFactory)
+register(PlateContainerFactory)
+register(MaterialTableFactory)
 
 
 @pytest.fixture()
diff --git a/tests/entities/factories.py b/tests/entities/factories.py
index c3eb73f9..3d85e8fd 100644
--- a/tests/entities/factories.py
+++ b/tests/entities/factories.py
@@ -8,6 +8,7 @@
     Excel,
     Experiment,
     Image,
+    MaterialsTable,
     Notebook,
     PowerPoint,
     Spotfire,
@@ -119,3 +120,10 @@ class Meta:
         model = UploadedResource
 
     type = EntityType.UPLOADED_RESOURCE
+
+
+class MaterialTableFactory(EntityFactory):
+    class Meta:
+        model = MaterialsTable
+
+    type = EntityType.MATERIAL_TABLE
diff --git a/tests/entities/plates/__init__.py b/tests/entities/plates/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/entities/plates/factories.py b/tests/entities/plates/factories.py
new file mode 100644
index 00000000..594eda29
--- /dev/null
+++ b/tests/entities/plates/factories.py
@@ -0,0 +1,10 @@
+from signals_notebook.common_types import EntityType
+from signals_notebook.entities import PlateContainer
+from tests.entities.factories import EntityFactory
+
+
+class PlateContainerFactory(EntityFactory):
+    class Meta:
+        model = PlateContainer
+
+    type = EntityType.PLATE_CONTAINER
diff --git a/tests/entities/plates/snapshots/__init__.py b/tests/entities/plates/snapshots/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/entities/plates/snapshots/snap_test_plate_container.py b/tests/entities/plates/snapshots/snap_test_plate_container.py
new file mode 100644
index 00000000..35854e24
--- /dev/null
+++ b/tests/entities/plates/snapshots/snap_test_plate_container.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+# snapshottest: v1 - https://goo.gl/zC4yUc
+from __future__ import unicode_literals
+
+from snapshottest import Snapshot
+
+
+snapshots = Snapshot()
+
+snapshots['test_get_html 1'] = '''
+<div class="table-wrapper" style="margin: 10px 10px; padding: 6px 10px; border: solid 1px #f5f5f5;">
+    <div class="table-scroll">
+        <h2>name</h2>
+        <table>
+            <thead>
+                <tr>
+                
+                    <th>Well ID</th>
+                
+                    <th>Row</th>
+                
+                    <th>Column</th>
+                
+                    <th>Plate</th>
+                
+                    <th>Order</th>
+                
+                    <th>Plate ID</th>
+                
+                </tr>
+            </thead>
+            <tbody>
+                
+                <tr>
+                    
+                        
+                            <td>A1</td>
+                        
+                    
+                        
+                            <td>A</td>
+                        
+                    
+                        
+                            <td>1</td>
+                        
+                    
+                        
+                            <td>Plate-1</td>
+                        
+                    
+                        
+                            <td>1</td>
+                        
+                    
+                        
+                            <td></td>
+                        
+                    
+                </tr>
+                
+                <tr>
+                    
+                        
+                            <td>A2</td>
+                        
+                    
+                        
+                            <td>A</td>
+                        
+                    
+                        
+                            <td>2</td>
+                        
+                    
+                        
+                            <td>Plate-1</td>
+                        
+                    
+                        
+                            <td>1</td>
+                        
+                    
+                        
+                            <td></td>
+                        
+                    
+                </tr>
+                
+            </tbody>
+        </table>
+    </div>
+</div>
+'''
diff --git a/tests/entities/plates/test_plate_container.py b/tests/entities/plates/test_plate_container.py
new file mode 100644
index 00000000..811874ef
--- /dev/null
+++ b/tests/entities/plates/test_plate_container.py
@@ -0,0 +1,218 @@
+from uuid import UUID
+
+import pytest
+
+from signals_notebook.common_types import File
+from signals_notebook.entities.plates.cell import PlateCell
+from signals_notebook.entities.plates.plate_row import PlateRow
+
+
+@pytest.fixture()
+def plates_response():
+    return {
+        'links': {
+            'self': 'https://ex.com/api/rest/v1.0/plates/plateContainer:537d12b9-d8eb-46e8-b2e2-c50d1c01ba0a/summary'
+        },
+        'data': [
+            {
+                'type': 'plateRow',
+                'id': '869491dc-bf8b-3c43-a225-629e2c10900a',
+                'attributes': {
+                    'id': '869491dc-bf8b-3c43-a225-629e2c10900a',
+                    'type': 'plateRow',
+                    'cells': [
+                        {
+                            'key': '76a7d17a-75b7-39a5-8549-05f073a064e3',
+                            'type': 'TEXT',
+                            'name': 'Well ID',
+                            'content': {'user': 'A1', 'value': 'A1'},
+                        },
+                        {
+                            'key': '59f9b60c-a571-3c8e-982d-cdfe7e88e23c',
+                            'type': 'TEXT',
+                            'name': 'Row',
+                            'content': {'user': 'A', 'value': 'A'},
+                        },
+                        {
+                            'key': 'b5ff1ac8-310e-3848-9367-a4b8f4dc7ecc',
+                            'type': 'INTEGER',
+                            'name': 'Column',
+                            'content': {'user': '1', 'value': 1},
+                        },
+                        {
+                            'key': '5a79aad4-7b07-39f1-9634-a2669a149a5b',
+                            'type': 'TEXT',
+                            'name': 'Plate',
+                            'content': {'user': 'Plate-1', 'value': 'Plate-1'},
+                        },
+                        {
+                            'key': '43a9fcf2-bf40-3ed0-ba54-204275f053df',
+                            'type': 'INTEGER',
+                            'name': 'Order',
+                            'content': {'user': '1', 'value': 1},
+                        },
+                        {
+                            'key': 'f2053c2d-985d-3343-97e4-ae35b7fbe9d3',
+                            'type': 'TEXT',
+                            'name': 'Plate ID',
+                            'content': {},
+                        },
+                    ],
+                },
+            },
+            {
+                'type': 'plateRow',
+                'id': '1b88b66a-598d-3552-bedc-aa468ea75776',
+                'attributes': {
+                    'id': '1b88b66a-598d-3552-bedc-aa468ea75776',
+                    'type': 'plateRow',
+                    'cells': [
+                        {
+                            'key': '76a7d17a-75b7-39a5-8549-05f073a064e3',
+                            'type': 'TEXT',
+                            'name': 'Well ID',
+                            'content': {'user': 'A2', 'value': 'A2'},
+                        },
+                        {
+                            'key': '59f9b60c-a571-3c8e-982d-cdfe7e88e23c',
+                            'type': 'TEXT',
+                            'name': 'Row',
+                            'content': {'user': 'A', 'value': 'A'},
+                        },
+                        {
+                            'key': 'b5ff1ac8-310e-3848-9367-a4b8f4dc7ecc',
+                            'type': 'INTEGER',
+                            'name': 'Column',
+                            'content': {'user': '2', 'value': 2},
+                        },
+                        {
+                            'key': '5a79aad4-7b07-39f1-9634-a2669a149a5b',
+                            'type': 'TEXT',
+                            'name': 'Plate',
+                            'content': {'user': 'Plate-1', 'value': 'Plate-1'},
+                        },
+                        {
+                            'key': '43a9fcf2-bf40-3ed0-ba54-204275f053df',
+                            'type': 'INTEGER',
+                            'name': 'Order',
+                            'content': {'user': '1', 'value': 1},
+                        },
+                        {
+                            'key': 'f2053c2d-985d-3343-97e4-ae35b7fbe9d3',
+                            'type': 'TEXT',
+                            'name': 'Plate ID',
+                            'content': {},
+                        },
+                    ],
+                },
+            },
+        ],
+    }
+
+
+@pytest.fixture()
+def plate_container_content():
+    return (
+        b'{"eid":"plateContainer:8728059f-8472-4872-929b-fa033e724fe3","name":"Plates-1","numberOfRows":32,'
+        + b'"numberOfColumns":48,"plates":[{"eid":"plate:f7cde4a2-f481-4c04-951f-83f59c45dd64","name":"Plate-1",'
+        + b'"plateCustomName":"d","plateContainerEid":"plateContainer:8728059f-8472-4872-929b-fa033e724fe3",'
+        + b'"isTemplate":false,"numberOfRows":32,"numberOfColumns":48,"annotationLayers":{},"fields":[]},'
+        + b'{"eid":"plate:0b34fefd-71e4-4bbd-ba56-df2363e64877","name":"Plate-2",'
+        + b'"plateContainerEid":"plateContainer:8728059f-8472-4872-929b-fa033e724fe3",'
+        + b'"isTemplate":false,"numberOfRows":32,"numberOfColumns":48,"annotationLayers":{},"fields":[]}],'
+        + b'"annotationLayers":[{"id":"9c41b7eb-e684-4354-9386-2bf97ae961a5",'
+        + b'"name":"Well Format","isPredefined":true,'
+        + b'"isHidden":false,"annotationClass":"wellformat","dataType":"TEXT","annotationLayerValues":{},'
+        + b'"trashed":false,"order":0,"suggestions":[]},{"id":"b31bfe68-daa9-45e5-bda7-6f65733c792c",'
+        + b'"name":"Concentration","isPredefined":true,"isHidden":false,"annotationClass":"concentration",'
+        + b'"dataType":"DECIMAL","annotationLayerValues":{},"trashed":false,"order":1,"suggestions":[]},'
+        + b'{"id":"212dfeb9-fa0d-49d5-927b-7c69054074a6","name":"Material","isPredefined":true,"isHidden":false,'
+        + b'"annotationClass":"material","dataType":"LINK","annotationLayerValues":{},"trashed":false,"order":2,'
+        + b'"suggestions":[]},{"id":"8dc52048-9c71-4442-b397-78bfdd164f4c","name":"Amount","isPredefined":true,'
+        + b'"isHidden":false,"annotationClass":"amount","dataType":"DECIMAL","annotationLayerValues":{},'
+        + b'"trashed":false,"order":3,"suggestions":[]},{"id":"e523e1dc-bb17-492e-8a9a-110060dfe561",'
+        + b'"name":"Replicate","isPredefined":true,"isHidden":false,"annotationClass":"replicate",'
+        + b'"dataType":"INTEGER","annotationLayerValues":{},"trashed":false,"order":4,"suggestions":[]},'
+        + b'{"id":"24ea6db0-56ab-4542-9e1f-3b116915cd21","name":"Deviation","isPredefined":true,"isHidden":false,'
+        + b'"annotationClass":"deviation","dataType":"TEXT","annotationLayerValues":{},"trashed":false,'
+        + b'"order":5,"suggestions":[]}],"fields":[]}'
+    )
+
+
+def test_get_content(api_mock, plate_container_factory, plate_container_content):
+    plate_container = plate_container_factory(name='name')
+    file_name = 'Test.json'
+    content = plate_container_content
+    content_type = 'application/json'
+
+    api_mock.call.return_value.headers = {
+        'content-type': content_type,
+        'content-disposition': f'attachment; filename={file_name}',
+    }
+    api_mock.call.return_value.content = content
+
+    result = plate_container.get_content()
+
+    api_mock.call.assert_called_once_with(
+        method='GET',
+        path=('entities', plate_container.eid, 'export'),
+        params={
+            'format': None,
+        },
+    )
+
+    assert isinstance(result, File)
+    assert result.name == file_name
+    assert result.content == content
+    assert result.content_type == content_type
+
+
+def test_get_html(api_mock, plate_container_factory, plates_response, snapshot):
+    plate_container = plate_container_factory(name='name')
+
+    api_mock.call.return_value.json.return_value = plates_response
+
+    plate_container_html = plate_container.get_html()
+
+    snapshot.assert_match(plate_container_html)
+
+
+@pytest.mark.parametrize(
+    'index', [1, '869491dc-bf8b-3c43-a225-629e2c10900a', UUID('869491dc-bf8b-3c43-a225-629e2c10900a')]
+)
+def test_getitem(api_mock, plate_container_factory, index, plates_response):
+    plate_container = plate_container_factory()
+
+    assert plate_container._rows == []
+    assert plate_container._rows_by_id == {}
+
+    api_mock.call.return_value.json.return_value = plates_response
+
+    plate = plate_container[0]
+    assert isinstance(plate, PlateRow)
+
+    assert plate_container._rows != []
+    assert plate_container._rows_by_id != {}
+
+    assert isinstance(plate_container[index], PlateRow)
+
+
+def test_iter(api_mock, plate_container_factory, plates_response):
+    plate_container = plate_container_factory()
+
+    assert plate_container._rows == []
+    assert plate_container._rows_by_id == {}
+
+    api_mock.call.return_value.json.return_value = plates_response
+
+    for plate in plate_container:
+        assert isinstance(plate, PlateRow)
+
+        plate_property = plate[0]
+        assert isinstance(plate_property, PlateCell)
+
+        for item in plate:
+            assert isinstance(item, PlateCell)
+
+    assert plate_container._rows != []
+    assert plate_container._rows_by_id != {}
diff --git a/tests/entities/snapshots/snap_test_materials_table.py b/tests/entities/snapshots/snap_test_materials_table.py
new file mode 100644
index 00000000..096caeeb
--- /dev/null
+++ b/tests/entities/snapshots/snap_test_materials_table.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# snapshottest: v1 - https://goo.gl/zC4yUc
+from __future__ import unicode_literals
+
+from snapshottest import Snapshot
+
+
+snapshots = Snapshot()
+
+snapshots['test_get_html 1'] = '''<div style="margin: 10px 10px; padding: 6px 10px; border: solid 1px #f5f5f5;">
+    <h2>name</h2>
+    
+    
+    <a href="data:text/csv;base64,U29tZSB0ZXh0" download="name.csv">DOWNLOAD .CSV FILE</a>
+    
+    
+</div>'''
diff --git a/tests/entities/test_materials_table.py b/tests/entities/test_materials_table.py
new file mode 100644
index 00000000..04d2996c
--- /dev/null
+++ b/tests/entities/test_materials_table.py
@@ -0,0 +1,46 @@
+from signals_notebook.common_types import File
+
+
+def test_get_content(material_table_factory, api_mock):
+    materials_table = material_table_factory()
+    file_name = 'Test.csv'
+    content = b'Some text'
+    content_type = 'text/csv'
+
+    api_mock.call.return_value.headers = {
+        'content-type': content_type,
+        'content-disposition': f'attachment; filename={file_name}',
+    }
+    api_mock.call.return_value.content = content
+
+    result = materials_table.get_content()
+
+    api_mock.call.assert_called_once_with(
+        method='GET',
+        path=('entities', materials_table.eid, 'export'),
+        params={
+            'format': None,
+        },
+    )
+
+    assert isinstance(result, File)
+    assert result.name == file_name
+    assert result.content == content
+    assert result.content_type == content_type
+
+
+def test_get_html(material_table_factory, snapshot, api_mock):
+    material_table = material_table_factory(name='name')
+    file_name = 'Test.csv'
+    content = b'Some text'
+    content_type = 'text/csv'
+
+    api_mock.call.return_value.headers = {
+        'content-type': content_type,
+        'content-disposition': f'attachment; filename={file_name}',
+    }
+    api_mock.call.return_value.content = content
+
+    material_table_html = material_table.get_html()
+
+    snapshot.assert_match(material_table_html)