diff --git a/production_tests.sh b/production_tests.sh
index b0d7d83ecc39ced5bb9b65c8f57ea6d80bd92290..e2934438b24c98a41da54e90d6f0e45898bacbfc 100755
--- a/production_tests.sh
+++ b/production_tests.sh
@@ -25,6 +25,11 @@ curl -X POST -H "Content-Type:application/json" -d '{"stationmeta_core": {"codes
 
 curl http://127.0.0.1:8000/timeseries/
 curl http://127.0.0.1:8000/timeseries/2
+# timeseries upload without nested fields
 curl -X POST -H "Content-Type:application/json" -d '{"timeseries": {"label": "CMA2", "order": 1, "access_rights": 0, "sampling_frequency": 0, "aggregation": 0, "data_start_date": "2003-09-07T15:30:00+02:00", "data_end_date": "2016-12-31T14:30:00+01:00", "measurement_method": "UV absorption", "sampling_height": 7.0, "date_added": "2020-05-15T15:30:00+02:00", "date_modified": "2020-05-16T09:30:00+02:00", "station_id": 2, "variable_id": 7, "additional_metadata":"{}"}}' http://127.0.0.1:8000/timeseries/
+# nested upload with enum fields
+curl -X POST -H "Content-Type:application/json" -d '{"timeseries": {"label": "CMA5", "order": 1, "access_rights": 0, "sampling_frequency": 0, "aggregation": 0, "data_start_date": "2003-09-07T15:30:00+02:00", "data_end_date": "2016-12-31T14:30:00+01:00", "measurement_method": "UV absorption", "sampling_height": 7.0, "date_added": "2020-05-15T15:30:00+02:00", "date_modified": "2020-05-16T09:30:00+02:00", "station_id": 2, "variable_id": 7, "additional_metadata":"{}", "roles": [{"role": 0, "person_id": 3, "status": 0},{"role": 1, "person_id": 3, "status": 0}]}}' http://127.0.0.1:8000/timeseries/
+# nested upload with human readable fields
+curl -X POST -H "Content-Type:application/json" -d '{"timeseries15:30:00+02:00", "data_end_date": "2016-12-31T14:30:00+01:00", "measurement_method": "UV absorption", "sampling_height": 7.0, "date_added": "2020-05-15T15:30:00+02:00", "date_modified": "2020-05-16T09:30:00+02:00", "station_id": 2, "variable_id": 7, "additional_metadata":"{}", "roles": [{"role": "PointOfContact", "person": "s.schroeder@fz-juelich.de", "status": "active"},{"role": "Originator", "person": "Stefan.Feigenspan@uba.de", "status": "active"}]}}' http://127.0.0.1:8000/timeseries/
 
 curl -X POST -H 'Content-Type: multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__' -F "file=@o3_CO002_2012_2017_v1-0.dat" "http://127.0.0.1:8000/data/"
diff --git a/toardb/timeseries/crud.py b/toardb/timeseries/crud.py
index 7abde3481ef1108e29f592650953c15dcc1d93e2..f8dc8369fc2f2316621df35d02444bbfcf695d31 100644
--- a/toardb/timeseries/crud.py
+++ b/toardb/timeseries/crud.py
@@ -7,6 +7,7 @@ Create, Read, Update, Delete functionality
 from sqlalchemy.orm import Session
 from fastapi.responses import JSONResponse
 from . import models
+from .models import RS_enum, RC_enum
 from .schemas import TimeseriesCreate
 
 
@@ -23,6 +24,11 @@ def get_all_timeseries(db: Session, skip : int = 0, limit: int = None):
     for db_object in db_objects:
         # there is a mismatch with additional_metadata
         db_object.additional_metadata = str(db_object.additional_metadata)
+        # add roles (model does not have them!)
+        # do I need a second model?! (not related to the real database?!)
+        roles = get_role_ids_of_timeseries(db, int(db_object.id))
+        print("====================roles ==================", db_object.id, roles)
+    # now return for schema TimeseriesCore (model.Timeseries has no roles!)
     return db_objects
 
 
@@ -37,8 +43,37 @@ def get_timeseries_by_unique_constraints(db: Session, station_id: int, variable_
     return db_object
 
 
+# is this internal, or should this also go to public REST api?
+def get_role_ids_of_timeseries(db: Session, timeseries_id: int):
+    db_objects = db.query(models.TimeseriesTimeseriesRoles) \
+                                      .filter(models.TimeseriesTimeseriesRoles.timeseries_id == timeseries_id) \
+                                      .all()
+    return db_objects
+
+
+# is this internal, or should this also go to public REST api?
+def get_unique_timeseries_role(db: Session, role: int, person_id: int, status: int):
+    db_object = db.query(models.TimeseriesRole).filter(models.TimeseriesRole.role == role) \
+                                      .filter(models.TimeseriesRole.person_id == person_id) \
+                                      .filter(models.TimeseriesRole.status == status) \
+                                      .first()
+    return db_object
+
+
+def __get_status_enum(db: Session):
+    return db.query(RS_enum).all()
+
+
+def __get_role_enum(db: Session):
+    return db.query(RC_enum).all()
+
+
 def create_timeseries(db: Session, timeseries: TimeseriesCreate):
-    db_timeseries = models.Timeseries (**timeseries.dict())
+    enum_RS = __get_status_enum(db)
+    enum_RC = __get_role_enum(db)
+    timeseries_dict = timeseries.dict()
+    roles_data = timeseries_dict.pop('roles', None)
+    db_timeseries = models.Timeseries(**timeseries_dict)
     # there's also a mismatch with additional_metadata --> BUT: this should not be switched back!
     # in upload command, we have now: "additional_metadata": "{}"
     # but return from this method gives: "additional_metadata": {}
@@ -47,4 +82,29 @@ def create_timeseries(db: Session, timeseries: TimeseriesCreate):
     db.add(db_timeseries)
     result = db.commit()
     db.refresh(db_timeseries)
+    # get timeseries_id
+    timeseries_id = db_timeseries.id
+    # store roles and update associaton table
+    for r in roles_data:
+        # try which format is used
+        try:
+            db_role = models.TimeseriesRole(**r)
+        except:
+            print ("human readable format: ", roles_data)
+        # check whether role is already present in database
+        db_object = get_unique_timeseries_role(db, db_role.role, db_role.person_id, db_role.status)
+        if db_object:
+            role_id = db_object.id
+        else:
+            db.add(db_role)
+            db.commit()
+            db.refresh(db_role)
+            role_id = db_role.id
+        r['id'] = role_id
+        # now into associaton table!
+        db_assoc = models.TimeseriesTimeseriesRoles(timeseries_id=timeseries_id, role_id=role_id)
+        db.add(db_assoc)
+        db.commit()
+        db.refresh(db_assoc)
+    setattr(db_timeseries,'roles',roles_data)
     return db_timeseries
diff --git a/toardb/timeseries/models.py b/toardb/timeseries/models.py
index 475ca4805a09c5c01ac96104544e7d06e6a722f4..400dbd8a02c85a70313169d8fd8c891a12ad7170 100644
--- a/toardb/timeseries/models.py
+++ b/toardb/timeseries/models.py
@@ -3,6 +3,8 @@ from sqlalchemy import MetaData
 from sqlalchemy.ext.declarative import declarative_base
 from .models_core import (
         Timeseries,
+        TimeseriesRole,
+        TimeseriesTimeseriesRoles,
         Base as TimeseriesBase)
 from .models_annotation import (
         TimeseriesAnnotation,
@@ -14,7 +16,7 @@ from .models_programme import (
 Base = declarative_base()
 metadata = MetaData()
 
-from sqlalchemy import Column, ForeignKey, Integer
+from sqlalchemy import Table, String, Column, ForeignKey, Integer
 from sqlalchemy.ext.declarative import declarative_base
 
 Base = declarative_base()
@@ -92,3 +94,17 @@ Foreign-key constraints:
 ##     role_id = Column(Integer, ForeignKey(TimeseriesRole.id), primary_key=True, nullable=False)
 
 
+# controlled vocabulary
+RS_enum = Table("rs_vocabulary",
+                metadata,
+                Column("enum_val", Integer, primary_key=True),
+                Column("enum_str", String),
+                Column("enum_display_str", String)
+          )
+
+RC_enum = Table("rc_vocabulary",
+                metadata,
+                Column("enum_val", Integer, primary_key=True),
+                Column("enum_str", String),
+                Column("enum_display_str", String)
+          )
diff --git a/toardb/timeseries/models_core.py b/toardb/timeseries/models_core.py
index f0d9556255e56b4da54f7aae18987f33beda5457..1ac610f18169e7407d7e2a75202e95ce01ba2d25 100644
--- a/toardb/timeseries/models_core.py
+++ b/toardb/timeseries/models_core.py
@@ -63,7 +63,7 @@ class TimeseriesTimeseriesRoles(Base):
 #  role_id = Column(ForeignKey(TimeseriesRole.id, deferrable=True, initially='DEFERRED'))
    timeseries_id = Column(ForeignKey('timeseries.id', deferrable=True, initially='DEFERRED'))
    role_id = Column(ForeignKey('timeseries_roles.id', deferrable=True, initially='DEFERRED'))
-##   timeseries = relationship(Timeseries, back_populates = 'role')
+##   timeseries = relationship(Timeseries, back_populates = 'roles')
 ##   roles = relationship(TimeseriesRole, back_populates = 'timeseries')
 
 
@@ -108,10 +108,10 @@ class TimeseriesRole(Base):
 # see: https://groups.google.com/forum/#!topic/sqlalchemy/YjGhE4d6K4U
     person_id = Column(ForeignKey(Person.id, deferrable=True, initially='DEFERRED'), nullable=False, index=True)
 # how to reactivate the following line
-#   person = relationship('Person')
+    person = relationship(Person)
 
 # how to reactivate the following line?!
-    timeseries_id = Column(Integer, ForeignKey(Timeseries.id), nullable=False)
+#   timeseries_id = Column(Integer, ForeignKey(Timeseries.id), nullable=False)
 #   timeseries = relationship(Timeseries, secondary=timeseries_timeseries_roles, backref="timeseries")
     timeseries = relationship(Timeseries, secondary=TimeseriesTimeseriesRoles.__table__, backref="timeseries")
 
diff --git a/toardb/timeseries/schemas.py b/toardb/timeseries/schemas.py
index 8cf229e3b5261dc65ba21224055684094741ed59..ec24f36b529a6dd2b85727b5250912b9f3e26e76 100644
--- a/toardb/timeseries/schemas.py
+++ b/toardb/timeseries/schemas.py
@@ -11,7 +11,7 @@ import datetime as dt
 
 # ======== Timeseries =========
 
-class TimeseriesBase(BaseModel):
+class TimeseriesCoreBase(BaseModel):
     id: int = None
     label: str
     order: int
@@ -29,11 +29,11 @@ class TimeseriesBase(BaseModel):
     additional_metadata: Json
 
 
-class TimeseriesCreate(TimeseriesBase):
+class TimeseriesCoreCreate(TimeseriesCoreBase):
     pass
 
 
-class Timeseries(TimeseriesBase):
+class TimeseriesCore(TimeseriesCoreBase):
     id: int
 
     class Config:
@@ -46,8 +46,6 @@ class TimeseriesRoleBase(BaseModel):
     role: int
     status: int
     person_id: int
-    timeseries_id: int
-
 
 class TimeseriesRoleCreate(TimeseriesRoleBase):
     pass
@@ -101,3 +99,24 @@ class TimeseriesProgramme(TimeseriesProgrammeBase):
     class Config:
         orm_mode = True
 
+# ======== for nested view/upload =========
+
+class TimeseriesBase(TimeseriesCoreBase):
+    roles: List[TimeseriesRole]
+
+    class Config:
+        orm_mode = True
+
+class TimeseriesCreate(TimeseriesCoreBase):
+    roles: List[TimeseriesRoleBase]
+
+    class Config:
+        orm_mode = True
+
+
+class Timeseries(TimeseriesBase):
+    id: int
+
+    class Config:
+        orm_mode = True
+
diff --git a/toardb/timeseries/timeseries.py b/toardb/timeseries/timeseries.py
index 8c0fa82db69367c7fd4cd96b86545eb82f0ed1ba..52d6b1cc6cba49545836ae25cb92c4279739f565 100644
--- a/toardb/timeseries/timeseries.py
+++ b/toardb/timeseries/timeseries.py
@@ -23,7 +23,7 @@ def get_db():
 # plain views to post and get timeseries
 
 #get all entries of table timeseries
-@router.get('/timeseries/', response_model=List[schemas.Timeseries])
+@router.get('/timeseries/', response_model=List[schemas.TimeseriesCore])
 def get_all_timeseries(skip: int = 0, limit: int = None, db: Session = Depends(get_db)):
     timeseries = crud.get_all_timeseries(db, skip=skip, limit=limit)
     return timeseries