diff --git a/examples/timeseries.py b/examples/timeseries.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f7c92166c1983261f99e274bb50ada1acd9cd04
--- /dev/null
+++ b/examples/timeseries.py
@@ -0,0 +1,51 @@
+import logging
+import os
+
+from grid5000 import Grid5000
+
+import pandas as pd
+import matplotlib.pyplot as plt
+import seaborn as sns
+import time
+
+logging.basicConfig(level=logging.DEBUG)
+
+conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
+gk = Grid5000.from_yaml(conf_file)
+
+metrics = gk.sites["lyon"].metrics
+print("--- available metrics")
+print(metrics.list())
+
+print("---- power metric")
+print(metrics["power"])
+
+print("----- a timeserie")
+now = time.time()
+kwargs = {
+    "only": "nova-1,nova-2,nova-3",
+    "resolution": 1,
+    "from": int(now - 600),
+    "to": int(now)
+}
+
+# let's visualize this
+timeseries = metrics["power"].timeseries.list(**kwargs)
+df = pd.DataFrame()
+for timeserie in timeseries:
+    print(timeserie)
+    timestamp = timeserie.timestamps
+    value = timeserie.values
+    measurement = timeserie.uid
+    df = pd.concat([df, pd.DataFrame({
+        "timestamp": timestamp,
+        "value": value,
+        "measurement": [measurement]*len(timestamp)
+    })])
+
+sns.relplot(data=df,
+            x="timestamp",
+            y="value",
+            hue="measurement",
+            kind="line")
+plt.show()
\ No newline at end of file
diff --git a/grid5000/cli.py b/grid5000/cli.py
index 0d6131560b02fa825392cc72838cf614edc230e2..4a58df9daaaaf874a85eb0b5c9bdffb4b12073c5 100644
--- a/grid5000/cli.py
+++ b/grid5000/cli.py
@@ -37,6 +37,6 @@ def main():
     if not path.exists():
         print("Configuratio file %s is missing" % CONF_PATH)
         return
-    gk = Grid5000.from_yaml(CONF_PATH)
+    _ = Grid5000.from_yaml(CONF_PATH)
 
     IPython.embed(header=motd)
diff --git a/grid5000/objects.py b/grid5000/objects.py
index dc9f1208d637dc1cb0242ea48754ee752565fe7b..6103598a1ca9e0585db92da836c99aeb6a845d28 100644
--- a/grid5000/objects.py
+++ b/grid5000/objects.py
@@ -2,6 +2,14 @@ from .base import *  # noqa
 from .mixins import *  # noqa
 
 
+class Timeserie(RESTObject):
+    pass
+
+
+class Metric(RESTObject):
+    _managers = (("timeseries", "TimeserieManager"),)
+
+
 class Server(RESTObject):
     pass
 
@@ -63,7 +71,7 @@ class Job(RESTObject, RefreshMixin, ObjectDeleteMixin):
         try:
             _repr = ["%s:%s" % (k, getattr(self, k)) for k in keys]
             return "<%s %s>" % (self.__class__.__name__, " ".join(_repr))
-        except:
+        except Exception:
             return super().__repr__()
 
 
@@ -72,6 +80,7 @@ class Site(RESTObject):
         ("clusters", "ClusterManager"),
         ("deployments", "DeploymentManager"),
         ("jobs", "JobManager"),
+        ("metrics", "SiteMetricManager"),
         ("servers", "ServerManager"),
         ("status", "SiteStatusManager"),
         ("storage", "StorageHomeManager"),
@@ -302,3 +311,15 @@ class ServerManager(RESTManager, BracketMixin, RetrieveMixin):
     _path = "/sites/%(site)s/servers"
     _obj_cls = Server
     _from_parent_attrs = {"site": "uid"}
+
+
+class SiteMetricManager(RESTManager, BracketMixin, RetrieveMixin):
+    _path = "/sites/%(site)s/metrics"
+    _obj_cls = Metric
+    _from_parent_attrs = {"site": "uid"}
+
+
+class TimeserieManager(RESTManager, ListMixin):
+    _path = "/sites/%(site)s/metrics/%(metric)s/timeseries"
+    _obj_cls = Timeserie
+    _from_parent_attrs = {"site": "site", "metric": "uid"}