diff --git a/js/app/controllers/EpnTapModule.js b/js/app/controllers/EpnTapModule.js
index 13ec051..e875f47 100644
--- a/js/app/controllers/EpnTapModule.js
+++ b/js/app/controllers/EpnTapModule.js
@@ -27,8 +27,7 @@ Ext.define('amdaDesktop.EpnTapModule', {
 	Module initialisation. Called the first time that the user open the epnTap module.
 	*/
 	init: function() {
-		this.filter = Array();
-		this.selectedServiceId = null;
+		this.selectedService = null;
 
 		this.launcher = {
 			text: this.title,
@@ -38,18 +37,6 @@ Ext.define('amdaDesktop.EpnTapModule', {
 		};
 
 		this.aquireElements();
-
-		// create productTypeDict based on productTypesStore
-		this.productTypesStore.on({
-			load: function(store) {
-				this.productTypeDict = {};
-				for (var key in store.data.map) {
-					this.productTypeDict[key] = store.data.map[key].data.name;
-				}
-			},
-			scope: this
-		});
-
 		this.servicesStore.load();
 		this.productTypesStore.load();
 	},
@@ -60,20 +47,13 @@ Ext.define('amdaDesktop.EpnTapModule', {
 		this.granulesGrid = Ext.getCmp('epnTapGranulesGrid');
 		this.productTypeCB = Ext.getCmp('epnTapProductTypeCB');
 		this.targetNameCB = Ext.getCmp('epnTapTargetNameCB');
+		this.pagingTB = Ext.getCmp('epnTapPagingTB');
 		this.timeSelector = Ext.getCmp('epnTapTimeSelector');
-		this.rowsPerPageNf = Ext.getCmp('epnTapRowsPerPageNf');
-		this.currentPageLb = Ext.getCmp('epnTapCurrentPageLb');
-		this.totalPagesLb = Ext.getCmp('epnTapTotalPagesLb');
-		this.firstPageBtn = Ext.getCmp('epnTapFirstPageBtn');
-		this.previousPageBtn = Ext.getCmp('epnTapPreviousPageBtn');
-		this.nextPageBtn = Ext.getCmp('epnTapNextPageBtn');
-		this.lastPageBtn = Ext.getCmp('epnTapLastPageBtn');
 		this.getBtn = Ext.getCmp('epnTapGetBtn');
 
 		// stores elements
 		this.servicesStore = Ext.data.StoreManager.lookup('servicesStore');
 		this.granulesStore = Ext.data.StoreManager.lookup('granulesStore');
-		// this.metadataStore = Ext.data.StoreManager.lookup('metadataStore')
 		this.productTypesStore = Ext.data.StoreManager.lookup('productTypesStore');
 		this.targetNamesStore = Ext.data.StoreManager.lookup('targetNamesStore');
 	},
@@ -91,24 +71,8 @@ Ext.define('amdaDesktop.EpnTapModule', {
 			this.onServiceSelected(record);
 		}, this);
 
-		this.granulesGrid.on('cellclick', function(grid, td, cellIndex, record) {
-			this.onGranuleSelected(record.data['id']);
-		}, this);
-
-		this.firstPageBtn.on('click', function() {
-			this.onFirstPageBtnClicked();
-		}, this);
-
-		this.previousPageBtn.on('click', function() {
-			this.onPreviousPageBtnClicked();
-		}, this);
-
-		this.nextPageBtn.on('click', function() {
-			this.onNextPageBtnClicked();
-		}, this);
-
-		this.lastPageBtn.on('click', function() {
-			this.onLastPageBtnClicked();
+		this.pagingTB.on('beforechange', function(grid, td, cellIndex, record) {
+			this.onPageChanged();
 		}, this);
 
 		this.getBtn.on('click', function() {
@@ -120,43 +84,6 @@ Ext.define('amdaDesktop.EpnTapModule', {
 	*** Utils functions ***
 	**********************/
 
-	/**
-	Capitalize a name and replace underscores with spaces.
-	- `name`: The string to make pretty.
-	*/
-	prettify: function(name) {
-		return name.charAt(0).toUpperCase() + name.replace(/_/g, ' ').substr(1).toLowerCase();
-	},
-
-	/**
-	Capitalize a name, replace underscores with spaces, and write it in a plurial form.
-	- `name`: The string to make pretty.
-	*/
-	allPrettify: function(name) {
-		return 'All ' + (name[name.length-1] == 's' ? name : name + 's').replace(/_/g, ' ').toLowerCase();
-	},
-
-	isDate: function(date) {
-		if (date === null) {
-			return false;
-		}
-		var dateArr = date.split('/');
-		if (dateArr.length != 3 || isNaN(parseInt(dateArr[0])) || isNaN(parseInt(dateArr[1])) || isNaN(parseInt(dateArr[2])) ) {
-			return false;
-		}
-	return true;
-	},
-
-	/**
-	Disable or enable the navigation buttons (see `EpnTapUI.createNavigationPanel()`).
-	*/
-	disableNavBtns: function(firt, previous, next, last) {
-		this.firstPageBtn.setDisabled(firt);
-		this.previousPageBtn.setDisabled(previous);
-		this.nextPageBtn.setDisabled(next);
-		this.lastPageBtn.setDisabled(last);
-	},
-
 	updateGetBtnStatus: function() {
 		var shouldEnabled = this.targetNameCB.rawValue.length > 0 && this.productTypeCB.rawValue.length > 0;
 		if(shouldEnabled) {
@@ -167,10 +94,6 @@ Ext.define('amdaDesktop.EpnTapModule', {
 
 	},
 
-	/****************************
-	*** Service filter events ***
-	****************************/
-
 	/**
 	Called each time the epntap module is loaded.
 	- `target`: an array of 3 values: [target_name, dataproduct_type]; or null.
@@ -184,82 +107,17 @@ Ext.define('amdaDesktop.EpnTapModule', {
 		this.granulesStore.removeAll();
 
 		if(target) {
-			this.targetNameCB.getStore().add({'id': target[0], 'name': this.prettify(target[0])});
+			var name = target[0].charAt(0).toUpperCase() + target[0].replace(/_/g, ' ').substr(1).toLowerCase();
+			this.targetNameCB.getStore().add({'id': target[0], 'name': name});
 			this.targetNameCB.select(target[0]);
 			this.productTypeCB.select(target[1]);
 			this.updateNbResults();
 		}
 	},
 
-	/*********************
-	*** Buttons events ***
-	*********************/
-
-	/**
-	Trigerred when the `firstPageBtn` button is clicked (see `EpnTapUI.createNavigationPanel()`). Among other things,
-	send a new query and fill `granulesGrid`.
-	*/
-	onFirstPageBtnClicked: function() {
-		var newPageNumber = 1;
-		var limit = Number(this.rowsPerPageNf.value);
-		var offset = 0;
-		var selectedService = this.servicesStore.findRecord('id', this.selectedServiceId).data;
-
-		this.disableNavBtns(true, true, false, false);
-		this.currentPageLb.setText('' + newPageNumber);
-		loadMask.show();
-		AmdaAction.epnTapGetGranules(selectedService['table_name'], selectedService['access_url'], this.filter, limit, offset, this.fillGranules);
-	},
-
-	/**
-	Trigerred when the `previousPageBtn` button is clicked (see `EpnTapUI.createNavigationPanel()`). Among other things,
-	send a new query and fill `granulesGrid`.
-	*/
-	onPreviousPageBtnClicked: function() {
-		var newPageNumber = Number(this.currentPageLb.text) - 1;
-		var limit = Number(this.rowsPerPageNf.value);
-		var offset = (newPageNumber-1) * limit;
-		var selectedService = this.servicesStore.findRecord('id', this.selectedServiceId).data;
-
-		this.currentPageLb.setText('' + newPageNumber);
-		var isFirstPage = this.currentPageLb.text === '1';
-		this.disableNavBtns(isFirstPage, isFirstPage, false, false);
-		loadMask.show();
-		AmdaAction.epnTapGetGranules(selectedService['table_name'], selectedService['access_url'], this.filter, limit, offset, this.fillGranules);
-	},
-
-	/**
-	Trigerred when the `nextPageBtn` button is clicked (see `EpnTapUI.createNavigationPanel()`). Among other things,
-	send a new query and fill `granulesGrid`.
-	*/
-	onNextPageBtnClicked: function() {
-		var newPageNumber = Number(this.currentPageLb.text) + 1;
-		var limit = Number(this.rowsPerPageNf.value);
-		var offset = (newPageNumber-1) * limit;
-		var selectedService = this.servicesStore.findRecord('id', this.selectedServiceId).data;
-
-		this.currentPageLb.setText('' + newPageNumber);
-		var isLastPage = this.currentPageLb.text == this.totalPagesLb.text;
-		this.disableNavBtns(false, false, isLastPage, isLastPage);
-		loadMask.show();
-		AmdaAction.epnTapGetGranules(selectedService['table_name'], selectedService['access_url'], this.filter, limit, offset, this.fillGranules);
-	},
-
-	/**
-	Trigerred when the `lastPageBtn` button is clicked (see `EpnTapUI.createNavigationPanel()`). Among other things,
-	send a new query and fill `granulesGrid`.
-	*/
-	onLastPageBtnClicked: function() {
-		var newPageNumber = Number(this.totalPagesLb.text);
-		var limit = Number(this.rowsPerPageNf.value);
-		var offset = (newPageNumber-1) * limit;
-		var selectedService = this.servicesStore.findRecord('id', this.selectedServiceId).data;
-
-		this.currentPageLb.setText('' + newPageNumber);
-		this.disableNavBtns(false, false, true, true);
-		loadMask.show();
-		AmdaAction.epnTapGetGranules(selectedService['table_name'], selectedService['access_url'], this.filter, limit, offset, this.fillGranules);
-	},
+	/*************
+	*** Events ***
+	*************/
 
 	/**
 	Trigerred when the 'Get results' button is clicked.
@@ -272,6 +130,7 @@ Ext.define('amdaDesktop.EpnTapModule', {
 
 		loadMask.show();
 		this.servicesStore.each(function(record) {
+			// TODO: use store.load() method instead.
 			Ext.Ajax.request({
 				url: 'php/epntap.php',
 				method: 'GET',
@@ -318,114 +177,46 @@ Ext.define('amdaDesktop.EpnTapModule', {
 		loadMask.hide();
 	},
 
-	/*******************
-	*** Grids events ***
-	*******************/
-
-	/**
-	Trigerred when a row is clicked in `servicesGrid` table (see `EpnTapUI.createServicesGrid()`). Among other things,
-	send a new query and fill `granulesGrid`.
-	*/
-	onServiceSelected: function(record) {
-		var nbRes = record.get('nb_results');
-		if(nbRes <= 0 || isNaN(nbRes)) {
-			return;
+	getGranuleParams: function() {
+		return {
+			'action': 'getGranules',
+			'url': this.selectedService.data['access_url'],
+			'tableName': this.selectedService.data['table_name'],
+			'targetName': this.targetNameCB.rawValue,
+			'productTypes': this.productTypeCB.value.join(';'),
+			'timeMin': Ext.Date.format(this.timeSelector.getStartTime(), 'd/m/Y H:i:s'),
+			'timeMax': Ext.Date.format(this.timeSelector.getStopTime(), 'd/m/Y H:i:s'),
+			'nbRes': this.selectedService.get('nb_results')
 		}
-		var targetName = this.targetNameCB.rawValue;
-		var productTypes = this.productTypeCB.value.join(';');
-		var timeMin = Ext.Date.format(this.timeSelector.getStartTime(), 'd/m/Y H:i:s'); // start time
-		var timeMax = Ext.Date.format(this.timeSelector.getStopTime(), 'd/m/Y H:i:s'); // stop time
-
-		loadMask.show();
-		Ext.Ajax.request({
-			url: 'php/epntap.php',
-			method: 'GET',
-			headers: {'Content-Type': 'application/json'},
-			// waitTitle: 'Connecting',
-			// waitMsg: 'Sending data...',
-			params: {
-				'action': 'getGranules',
-				'url': record.data['access_url'],
-				'tableName': record.data['table_name'],
-				'targetName': targetName,
-				'productTypes': productTypes,
-				'timeMin': timeMin,
-				'timeMax': timeMax,
-				'top': this.rowsPerPageNf.value,
-				'offset': 0
-			},
-			success: this.updateGranules,
-			failure: this.updateGranulesFail,
-			scope: this
-		});
 	},
 
-	updateGranules: function(response) {
-		try {
-			granules = JSON.parse(response.responseText);
-		} catch (e) {
-			response.responseText = 'Can not decode the returned Json.'
-			this.updateGranulesFail(response);
-		}
-		this.granulesStore.add(granules);
-		loadMask.hide();
+	onPageChanged: function() {
+		var myProxy = this.granulesStore.getProxy();
+		myProxy.params = this.getGranuleParams();
+		myProxy.extraParams = this.getGranuleParams();
+		// //--- Set value to your parameter  ----//
+		// myProxy.setExtraParam('url', this.selectedService.data['access_url']);
+  // myProxy.setExtraParam('MENU_DETAIL', '555555');
 	},
-
 	/**
-	Trigerred when a row is clicked in `granulesGrid` table (see `EpnTapUI.createGranulesGrid()`).
-	*/
-	updateGranulesFail: function(granule) {
-		var reason = response.status === 200 ? response.responseText : response.statusText;
-		Ext.Msg.alert('Can not display granules: ' + reason);
-		loadMask.hide();
-		// console.log('selected granule: ', granule);
-	},
-
-	/**********************
-	*** Other functions ***
-	**********************/
-
-	/**
-	Callback function, called from the PHP script when the query result is received, when a service is selected.
-
-	Among other things, update the `epnTapCurrentPageLb` label (see `EpnTapUI.createNavigationPanel()`).
-	*/
-	updateNbRows: function(nb_results) {
-		var totalPages = Math.ceil(Number(nb_results) / Ext.getCmp('epnTapRowsPerPageNf').value);
-
-		Ext.getCmp('epnTapCurrentPageLb').setText(totalPages == 0 ? '-' : '1');
-		Ext.getCmp('epnTapTotalPagesLb').setText(totalPages == 0 ? '-' : totalPages);
-
-		Ext.getCmp('epnTapPreviousPageBtn').setDisabled(true);
-		Ext.getCmp('epnTapFirstPageBtn').setDisabled(true);
-		Ext.getCmp('epnTapNextPageBtn').setDisabled(totalPages <= 1);
-		Ext.getCmp('epnTapLastPageBtn').setDisabled(totalPages <= 1);
-	},
-
-	/**
-	Callback function, called from the PHP script when the query result is received, when a service is selected or a
-	navigation button is clicked.
-
-	Among other things, fill the `epnTapGranulesGrid` table (see `EpnTapUI.granulesStore`).
+	Trigerred when a row is clicked in `servicesGrid` table (see `EpnTapUI.createServicesGrid()`). Among other things,
+	send a new query and fill `granulesGrid`.
 	*/
-	fillGranules: function(granules) {
-		loadMask.hide();
-
-		if (granules["error"] != null) {
-			console.log('Can not get request response:', granules["error"]);
-			if(granules["error"] == "no result") {
-				Ext.Msg.alert('There is no result for this query.');
-			} else {
-				Ext.Msg.alert('Can not display granules due to an error from the selected epn-tap service.');
-			}
-		} else {
-			try {
-				Ext.getCmp('epnTapGranulesGrid').getStore().removeAll();
-				Ext.getCmp('epnTapGranulesGrid').getStore().add(granules);
-			} catch( e ) {
-				console.log('Can not add granules: ' + e);
-				Ext.Msg.alert('Can not display granules due to an error from the selected epn-tap service.');
-			}
+	onServiceSelected: function(record) {
+		this.selectedService = record;
+		var nbRes = this.selectedService.get('nb_results');
+		if(nbRes > 0 && !isNaN(nbRes)) {
+			loadMask.show();
+			this.granulesStore.load({
+				params: this.getGranuleParams(),
+				start: 0,
+				limit: this.granulesStore.pageSize,
+				callback: function(records, operation, success) {
+					console.log(records, operation);
+					loadMask.hide();
+				},
+				scope: this
+			});
 		}
 	}
 });
diff --git a/js/app/views/EpnTapUI.js b/js/app/views/EpnTapUI.js
index 3021a93..337da87 100644
--- a/js/app/views/EpnTapUI.js
+++ b/js/app/views/EpnTapUI.js
@@ -137,7 +137,20 @@ selected.
 */
 Ext.create('Ext.data.Store', {
 	storeId:'granulesStore',
-	fields:['num', 'dataproduct_type', 'target_name', 'time_min', 'time_max', 'access_format', 'granule_uid', 'access_estsize', 'access_url', 'thumbnail_url']
+	pageSize: 25,
+	autoload: false,
+	fields:['num', 'dataproduct_type', 'target_name', 'time_min', 'time_max', 'access_format', 'granule_uid', 'access_estsize', 'access_url', 'thumbnail_url'],
+	proxy: {
+		type: 'ajax',
+		url: 'php/epntap.php',
+		reader: {
+			type: 'json',
+			root: 'rows'
+		}
+	},
+	sorters: [
+		{property: 'num', direction: 'ASC'}
+	]
 });
 
 /**
@@ -217,8 +230,6 @@ Ext.define('amdaUI.EpnTapUI', {
 			}, { // Right part
 				xtype : 'container',
 				items: [
-					this.createRowPerPageNf(),
-					this.createNavigationPanel(),
 					this.createSendButton()
 				]
 
@@ -332,92 +343,6 @@ Ext.define('amdaUI.EpnTapUI', {
 	***********************/
 
 	/**
-	Create `epnTapRowsPerPageNf`, a ExtJS Number field, allowing the user to select the number of rows to display in
-	`epnTapGranulesGrid`.
-
-	When a new number is entered, it triggers `EpnTapModule.onRowsPerPageChanged()`.
-	*/
-	createRowPerPageNf: function() {
-		return {
-			xtype: 'numberfield',
-			id: 'epnTapRowsPerPageNf',
-			fieldLabel: 'Rows per page',
-			labelWidth: 85,
-			margin: '4 0 4 0',
-			width: 140,
-			height: 20,
-			value: 20,
-			minValue: 1,
-			maxValue: 2000
-		};
-	},
-
-	/**
-	Create `epnTapNavigationPanel`, an ExtJSPanel containing several elements in order to navigate through the
-	different pages of the query result. If the number of results is highter than the `epnTapRowsPerPageNf` field
-	value, the result appears to be displayed in different pages. This panel is used to select and display the page
-	number, mainly with these following elements:
-	- `epnTapFirstPageBtn`: an ExtJS Button, used to come back to the first page of result,
-			handling `EpnTapModule.onFirstPageBtnClicked()`;
-	- `epnTapPreviousPageBtn`: an ExtJS Button, used to come back to the previous page of result,
-			handling `EpnTapModule.onPreviousPageBtnClicked()`;
-	- `epnTapCurrentPageLb`: an ExtJS Label, displaying the actual current page; TODO: use a Number field instead!
-	- `epnTapTotalPagesLb`: an ExtJS Label, displaying the total page number of results (according to the
-	`epnTapRowsPerPageNf` field value);
-	- `epnTapNextPageBtn`: an ExtJS Button, used to go to the next page of result,
-			handling `EpnTapModule.onNextPageBtnClicked()`;
-	- `epnTapLastPageBtn`: an ExtJS Button, used to come back to the last page of result,
-			handling `EpnTapModule.onLastPageBtnClicked()`.
-
-	Note: Pages are not actually a "graphical filter": when the user navigate through the pages, a new query is send
-	to the server with the corresponding range, which improves the response time on large requests.
-	*/
-	createNavigationPanel: function() {
-		return {
-			xtype: 'container',
-			width: 145,
-			defaults: {margin: '0 5 0 0', xtype: 'button', disabled: true},
-			items: [{
-				id: 'epnTapFirstPageBtn',
-				text: '|<',
-				width: 26,
-				tooltip: 'First page'
-			}, {
-				id: 'epnTapPreviousPageBtn',
-				text: '<',
-				width: 26,
-				tooltip: 'Previous page'
-			}, {
-				xtype: 'label',
-				id: 'epnTapCurrentPageLb',
-				tooltip: 'Current page',
-				text: '0',
-				margin: 0
-			}, {
-				xtype: 'label',
-				text: '/',
-				margin: 0
-			}, {
-				xtype: 'label',
-				id: 'epnTapTotalPagesLb',
-				tooltip: 'Total pages',
-				text: '0',
-			}, {
-				id: 'epnTapNextPageBtn',
-				text: '>',
-				width: 26,
-				tooltip: 'Next page'
-			}, {
-				id: 'epnTapLastPageBtn',
-				text: '>|',
-				width: 26,
-				margin: 0,
-				tooltip: 'Last page'
-			}]
-		};
-	},
-
-	/**
 	The button used to send the query.
 	*/
 	createSendButton: function() {
@@ -427,7 +352,8 @@ Ext.define('amdaUI.EpnTapUI', {
 			text: 'Get results',
 			disabled: true,
 			width: 140,
-			margin: '5 0 0 0'
+			height: 50,
+			margin: 10
 		}
 	},
 
@@ -670,6 +596,30 @@ Ext.define('amdaUI.EpnTapUI', {
 				{ text: 'URL', dataIndex: 'access_url', flex: 1, renderer: linkRender },
 				{ text: 'Thumb.', dataIndex: 'thumbnail_url', flex: 1, renderer: imgRender}
 			],
+			dockedItems: [{
+				xtype: 'pagingtoolbar',
+				id: 'epnTapPagingTB',
+				store: Ext.data.StoreManager.lookup('granulesStore'),
+				dock: 'bottom',
+				displayInfo: true,
+				items: [{
+					xtype: 'tbseparator'
+				}, {
+					xtype: 'numberfield',
+					id: 'epnTapRowsPerPageNf',
+					fieldLabel: 'Rows per page',
+					labelWidth: 78,
+					width: 150,
+					value: Ext.data.StoreManager.lookup('granulesStore').pageSize,
+					minValue: 1,
+					maxValue: 2000,
+					listeners: {
+						change: function(newValue, oldValue) {
+							Ext.data.StoreManager.lookup('granulesStore').pageSize = newValue;
+						}
+					}
+				}]
+			}],
 			renderTo: Ext.getBody()
 		});
 
diff --git a/php/epntap.php b/php/epntap.php
index 4cf1c3f..82b2fb0 100644
--- a/php/epntap.php
+++ b/php/epntap.php
@@ -80,6 +80,8 @@ function getNbResults() {
 		return 'Too few returned raws.';
 	} else if(count($result) > 1) {
 		return 'Too many returned raws.';
+	} else if(!array_key_exists(0, $result)) {
+		return 'cant find raw item 0';
 	} else if(is_null($result[0])) {
 		return 'The returned raw is null.';
 	} else if(!array_key_exists("nb_rows", $result[0])) {
@@ -92,21 +94,24 @@ function getNbResults() {
 }
 
 function getGranules() {
+	error_log(json_encode($_GET));
 	$url = filter_var($_GET['url'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 	$tableName = filter_var($_GET['tableName'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 	$targetName = filter_var($_GET['targetName'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 	$productTypes = filter_var($_GET['productTypes'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 	$timeMin = filter_var($_GET['timeMin'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 	$timeMax = filter_var($_GET['timeMax'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
-	$top = filter_var($_GET['top'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
-	$offset = filter_var($_GET['offset'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
+	$start = filter_var($_GET['start'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
+	$limit = filter_var($_GET['limit'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
+	$nbRes = filter_var($_GET['nbRes'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
 
 	// TODO find a way to handle 'non existing key errors' (and then add access_format)
 	$columns = "dataproduct_type, target_name, time_min, time_max, granule_uid, access_estsize, access_url, thumbnail_url";
 	$filter = createFilter($targetName, $productTypes, $timeMin, $timeMax);
-	$query = "SELECT TOP $top $columns FROM $tableName $filter OFFSET $offset";
-	$result = request($url, $query);
-	return $result;
+	$query = "SELECT TOP $limit $columns FROM $tableName $filter OFFSET $start";
+	$rows = request($url, $query);
+	return ['success' => true, 'total' => $nbRes, 'rows' => $rows];
+	// return $rows;
 }
 
 // ----- utils -----
--
libgit2 0.21.2