diff --git a/alta/__init__.py b/alta/__init__.py
index ee19b2c4fb3933a3d82460df7fba77a7e39a322b..93ccfeb7fb70ca0134a242efb6d03e3837e5e065 100644
--- a/alta/__init__.py
+++ b/alta/__init__.py
@@ -1 +1 @@
-from .alta_connector import alta_connector
+from alta.alta_connector import alta_connector
diff --git a/alta/alta_example.py b/alta/alta_example.py
index 14ec71d6c81bfc0a78ea7b3200035c10e7f7b4dc..8a35f671a28637ee49ef8acfc3c0d4f463b65910 100644
--- a/alta/alta_example.py
+++ b/alta/alta_example.py
@@ -1,18 +1,45 @@
 from shopping_client import shopping_client
 from alta import alta_connector
+from astron_vo import astron_vo_connector
+from samp import samp_connector
 
 esap_api_host = "https://sdc-dev.astron.nl:5555/"
+#access_token = ""
 
 # Instantiate alta connector
 ac = alta_connector()
+vo = astron_vo_connector()
 
 # Instantiate ESAP User Profile shopping client, passing alta connector
-#sc = shopping_client(host=esap_api_host, token=access_token, connectors=[ac])
+#sc = shopping_client(host=esap_api_host, token=access_token, connectors=[ac,vo])
 sc = shopping_client(host=esap_api_host, connectors=[ac])
 
-# Retrieve basket (prompts to enter access token obtained from ESAP GUI)
-basket=sc.get_basket(filter_archives=True)
+# 'apertif'and 'astron_vo' items converted to pandas dataframe
+basket_pandas=sc.get_basket(filter_archives=True, convert_to_pandas=True)
 
-print(basket)
-for item in basket:
-    print(item)
\ No newline at end of file
+print('------------------------------------')
+print("'apertif'and 'astron_vo' items converted to pandas dataframe")
+print(basket_pandas)
+
+# 'apertif'and 'astron_vo' items as json
+basket_json=sc.get_basket(filter_archives=True, convert_to_pandas=False)
+
+print('-----------------------------------')
+print("'apertif'and 'astron_vo' items as json")
+print(basket_json)
+
+samp_connector = samp_connector()
+sc = shopping_client(host=esap_api_host, token=access_token, connectors=[samp_connector])
+
+# "'SAMP' items converted to pandas dataframe:"
+basket_pandas=sc.get_basket(convert_to_pandas=True, filter_archives=True)
+
+print('------------------------------------')
+print("'SAMP' items converted to pandas dataframe:")
+print(basket_pandas)
+
+# 'SAMP' items as json:
+basket_json=sc.get_basket(convert_to_pandas=False, filter_archives=True)
+print('------------------------------------')
+print("'SAMP' items as json:")
+print(basket_json)
\ No newline at end of file
diff --git a/astron_vo/__init__.py b/astron_vo/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..00582d00bc41172f3df8b9100833568fe577f0e5
--- /dev/null
+++ b/astron_vo/__init__.py
@@ -0,0 +1 @@
+from astron_vo.astron_vo_connector import astron_vo_connector
diff --git a/astron_vo/astron_vo_connector.py b/astron_vo/astron_vo_connector.py
new file mode 100644
index 0000000000000000000000000000000000000000..32f848aba45ebcab657185166acb12a2aeb3c824
--- /dev/null
+++ b/astron_vo/astron_vo_connector.py
@@ -0,0 +1,74 @@
+import json
+
+import pandas as pd
+
+from typing import Union, Optional
+
+class astron_vo_connector:
+
+    name = "astron_vo"
+    archive = "astron_vo"
+
+    def basket_item_to_pandas(
+            self, basket_item: Union[dict, pd.Series], validate: bool = True
+    ) -> Optional[pd.Series]:
+        """Convert an item from the shopping basket into a `pd.Series` with
+        optional validation.
+
+        Parameters
+        ----------
+        basket_item : Union[dict, pd.Series]
+            A single item from a retrieved shopping basket - either a raw `dict`
+            or a converted `pd.Series`.
+        validate : bool
+            If `True`, check that the data in the shopping item conforms with
+            the expected format before attempting the conversion.
+
+        Returns
+        -------
+        Optional[pd.Series]
+            `pd.Series` containing the data encoded in the shopping item or
+            `NoneType`.
+
+        """
+        if validate:
+            item_data = self.validate_basket_item(basket_item, return_loaded=True)
+        else:
+            item_data = json.loads(basket_item["item_data"])
+        if item_data:
+            return pd.Series(item_data)
+        return None
+
+
+    def validate_basket_item(
+            self, basket_item: Union[dict, pd.Series], return_loaded: bool = False
+    ) -> Union[dict, bool, None]:
+        """Check that the data in the shopping item conforms with
+        the expected format
+
+        Parameters
+        ----------
+        basket_item : Union[dict, pd.Series]
+            A single item from a retrieved shopping basket - either a raw `dict`
+            or a converted `pd.Series`.
+        return_loaded : bool
+            If `True`, and validation succeeds return the extracted shopping item
+            as `dict`, otherwise return `True` if validation succeeds and `None`
+            otherwise.
+
+        Returns
+        -------
+        Union[dict, bool, None]
+            If `return_loaded` is `True`, return a `dict` containing the data
+            encoded in the shopping item when validation succeeds.
+            Otherwise if `return_loaded` is `True` validation succeeds.
+            If validation fails return `None`.
+
+        """
+        item_data = json.loads(basket_item["item_data"])
+        if "archive" in item_data and item_data["archive"] == self.archive:
+            if return_loaded:
+                return item_data
+            else:
+                return True
+        return None
\ No newline at end of file
diff --git a/samp/__init__.py b/samp/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7c8867ecd12e732119be64681b52abb6474dae1
--- /dev/null
+++ b/samp/__init__.py
@@ -0,0 +1 @@
+from samp.samp_connector import samp_connector
\ No newline at end of file
diff --git a/samp/samp_connector.py b/samp/samp_connector.py
new file mode 100644
index 0000000000000000000000000000000000000000..5035b6e03b06aa98504052ff8a29eba2890ad1e6
--- /dev/null
+++ b/samp/samp_connector.py
@@ -0,0 +1,76 @@
+import requests
+import json
+import io
+import getpass
+import pandas as pd
+
+from typing import Union, Optional
+
+class samp_connector:
+
+    name = "samp"
+    archive = "samp"
+
+    def basket_item_to_pandas(
+            self, basket_item: Union[dict, pd.Series], validate: bool = True
+    ) -> Optional[pd.Series]:
+        """Convert an item from the shopping basket into a `pd.Series` with
+        optional validation.
+
+        Parameters
+        ----------
+        basket_item : Union[dict, pd.Series]
+            A single item from a retrieved shopping basket - either a raw `dict`
+            or a converted `pd.Series`.
+        validate : bool
+            If `True`, check that the data in the shopping item conforms with
+            the expected format before attempting the conversion.
+
+        Returns
+        -------
+        Optional[pd.Series]
+            `pd.Series` containing the data encoded in the shopping item or
+            `NoneType`.
+
+        """
+        if validate:
+            item_data = self.validate_basket_item(basket_item, return_loaded=True)
+        else:
+            item_data = json.loads(basket_item["item_data"])
+        if item_data:
+            return pd.Series(item_data)
+        return None
+
+
+    def validate_basket_item(
+            self, basket_item: Union[dict, pd.Series], return_loaded: bool = False
+    ) -> Union[dict, bool, None]:
+        """Check that the data in the shopping item conforms with
+        the expected format
+
+        Parameters
+        ----------
+        basket_item : Union[dict, pd.Series]
+            A single item from a retrieved shopping basket - either a raw `dict`
+            or a converted `pd.Series`.
+        return_loaded : bool
+            If `True`, and validation succeeds return the extracted shopping item
+            as `dict`, otherwise return `True` if validation succeeds and `None`
+            otherwise.
+
+        Returns
+        -------
+        Union[dict, bool, None]
+            If `return_loaded` is `True`, return a `dict` containing the data
+            encoded in the shopping item when validation succeeds.
+            Otherwise if `return_loaded` is `True` validation succeeds.
+            If validation fails return `None`.
+
+        """
+        item_data = json.loads(basket_item["item_data"])
+        if "archive" in item_data and item_data["archive"] == self.archive:
+            if return_loaded:
+                return item_data
+            else:
+                return True
+        return None
\ No newline at end of file