diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/plugin.properties b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/plugin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..adce0389b097c5c796c556ca0f2e4f0df219925d
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/plugin.properties
@@ -0,0 +1,2 @@
+class = ch.ethz.sis.openbis.generic.server.asapi.v3.helper.service.JythonBasedCustomASServiceExecutor
+script-path = script.py
diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/script.py b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/script.py
new file mode 100644
index 0000000000000000000000000000000000000000..f60d2d2f4c5942586d8b9d9ce3b8858fc8e7acdf
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-a/script.py
@@ -0,0 +1,2 @@
+def process(context, parameters):
+    return "hello A"
diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/plugin.properties b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/plugin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..adce0389b097c5c796c556ca0f2e4f0df219925d
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/plugin.properties
@@ -0,0 +1,2 @@
+class = ch.ethz.sis.openbis.generic.server.asapi.v3.helper.service.JythonBasedCustomASServiceExecutor
+script-path = script.py
diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/script.py b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/script.py
new file mode 100644
index 0000000000000000000000000000000000000000..e88f260f90b524fb5c4803e5503b7624ac8b1ea0
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/custom-service-b/script.py
@@ -0,0 +1,2 @@
+def process(context, parameters):
+    return "hello B"
diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/plugin.properties b/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/plugin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9f16626ce634d11f219d95f9e177d25d78df4a95
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/plugin.properties
@@ -0,0 +1,3 @@
+class = ch.ethz.sis.openbis.generic.server.asapi.v3.helper.service.JythonBasedCustomASServiceExecutor
+description = a simple service
+script-path = script.py
diff --git a/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/script.py b/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/script.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed810fe411d51ffca8a186c7b142a87929b7b785
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/services/simple-service/script.py
@@ -0,0 +1,9 @@
+from ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions import SpaceFetchOptions
+from ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search import SpaceSearchCriteria
+
+def process(context, parameters):
+    spaceCode = parameters.get("space-code")
+    searchCriteria = SpaceSearchCriteria()
+    searchCriteria.withCode().thatEquals(spaceCode)
+    result = context.applicationService.searchSpaces(context.sessionToken, searchCriteria, SpaceFetchOptions())
+    return result
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
index 120d3678316287b6df2f49918dec3128525c3287..1add7a19cc4f1a25f0053664e7f3f2b7acb6cc4b 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
@@ -7,13 +7,17 @@ define([ 'jquery', 'openbis', 'as/dto/space/create/SpaceCreation', 'as/dto/proje
 		'as/dto/dataset/id/FileFormatTypePermId', 'as/dto/material/id/MaterialPermId', 'as/dto/tag/id/TagCode', 'as/dto/space/search/SpaceSearchCriteria', 'as/dto/project/search/ProjectSearchCriteria',
 		'as/dto/experiment/search/ExperimentSearchCriteria', 'as/dto/sample/search/SampleSearchCriteria', 'as/dto/dataset/search/DataSetSearchCriteria', 'as/dto/material/search/MaterialSearchCriteria',
 		'as/dto/space/fetchoptions/SpaceFetchOptions', 'as/dto/project/fetchoptions/ProjectFetchOptions', 'as/dto/experiment/fetchoptions/ExperimentFetchOptions', 'as/dto/sample/fetchoptions/SampleFetchOptions',
-		'as/dto/dataset/fetchoptions/DataSetFetchOptions', 'as/dto/material/fetchoptions/MaterialFetchOptions', 'as/dto/deletion/fetchoptions/DeletionFetchOptions', 'as/dto/deletion/search/DeletionSearchCriteria'
+		'as/dto/dataset/fetchoptions/DataSetFetchOptions', 'as/dto/material/fetchoptions/MaterialFetchOptions', 'as/dto/deletion/fetchoptions/DeletionFetchOptions', 'as/dto/deletion/search/DeletionSearchCriteria',
+		'as/dto/service/search/CustomASServiceSearchCriteria', 'as/dto/service/fetchoptions/CustomASServiceFetchOptions',
+		'as/dto/service/id/CustomASServiceCode', 'as/dto/service/CustomASServiceExecutionOptions'
 		 ], function($, openbis, SpaceCreation,
 		ProjectCreation, ExperimentCreation, SampleCreation, MaterialCreation, AttachmentCreation, SpaceUpdate, ProjectUpdate, ExperimentUpdate, SampleUpdate, DataSetUpdate, PhysicalDataUpdate,
 		MaterialUpdate, SpaceDeletionOptions, ProjectDeletionOptions, ExperimentDeletionOptions, SampleDeletionOptions, DataSetDeletionOptions, MaterialDeletionOptions, EntityTypePermId, SpacePermId,
 		ProjectPermId, ProjectIdentifier, ExperimentPermId, ExperimentIdentifier, SamplePermId, DataSetPermId, FileFormatTypePermId, MaterialPermId, TagCode, SpaceSearchCriteria,
 		ProjectSearchCriteria, ExperimentSearchCriteria, SampleSearchCriteria, DataSetSearchCriteria, MaterialSearchCriteria, SpaceFetchOptions, ProjectFetchOptions, ExperimentFetchOptions,
-		SampleFetchOptions, DataSetFetchOptions, MaterialFetchOptions, DeletionFetchOptions, DeletionSearchCriteria) {
+		SampleFetchOptions, DataSetFetchOptions, MaterialFetchOptions, DeletionFetchOptions, DeletionSearchCriteria,
+		CustomASServiceSearchCriteria, CustomASServiceFetchOptions,
+		CustomASServiceCode, CustomASServiceExecutionOptions) {
 
 	/*
 	 * These tests should be run against openBIS instance with screening sprint
@@ -76,6 +80,10 @@ define([ 'jquery', 'openbis', 'as/dto/space/create/SpaceCreation', 'as/dto/proje
 		this.MaterialFetchOptions = MaterialFetchOptions;
 		this.DeletionFetchOptions = DeletionFetchOptions;
 		this.DeletionSearchCriteria = DeletionSearchCriteria;
+		this.CustomASServiceSearchCriteria = CustomASServiceSearchCriteria;
+		this.CustomASServiceFetchOptions = CustomASServiceFetchOptions;
+		this.CustomASServiceCode = CustomASServiceCode;
+		this.CustomASServiceExecutionOptions = CustomASServiceExecutionOptions;
 
 		this.generateId = function(base) {
 			var date = new Date();
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/main.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/main.js
index 2d308c0f3350d1956efac73a004d59b9043565d0..b84adf7db28ab39e31f862108f665cedbb575305 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/main.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/main.js
@@ -1,4 +1,5 @@
-define([ 'test/test-login', 'test/test-jsVSjava', 'test/test-create', 'test/test-update', 'test/test-search', 'test/test-map', 'test/test-delete', 'test/test-dto' ], function() {
+define([ 'test/test-login', 'test/test-jsVSjava', 'test/test-create', 'test/test-update', 'test/test-search', 
+         'test/test-map', 'test/test-delete', 'test/test-dto', 'test/test-custom-services' ], function() {
 	var testSuites = arguments;
 	return function() {
 		for (var i = 0; i < testSuites.length; i++) {
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-custom-services.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-custom-services.js
new file mode 100644
index 0000000000000000000000000000000000000000..3f5fa396f53710611428f8cde8ea2c299d1f5988
--- /dev/null
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-custom-services.js
@@ -0,0 +1,65 @@
+/**
+ * Test searching and executing custom AS services.
+ */
+define(['jquery', 'underscore', 'openbis', 'test/common'], function($, _, openbis, common) {
+	return function() {
+		QUnit.module("Custom AS service tests")
+
+		var testAction = function(c, fAction, fCheck) {
+			c.start();
+
+			c.createFacadeAndLogin().then(function(facade) {
+				c.ok("Login");
+				return fAction(facade).then(function(result) {
+					c.ok("Got results");
+					fCheck(facade, result);
+					c.finish();
+				});
+			}).fail(function(error) {
+				c.fail(error.message);
+				c.finish();
+			});
+		}
+		
+		QUnit.test("searchCustomASServices()", function(assert) {
+			var c = new common(assert);
+			
+			var fAction = function(facade) {
+				var criteria = new c.CustomASServiceSearchCriteria();
+				criteria.withCode().thatStartsWith("simple");
+				return facade.searchCustomASServices(criteria, new c.CustomASServiceFetchOptions());
+			}
+
+			var fCheck = function(facade, result) {
+				var services = result.getObjects();
+				c.assertEqual(services.length, 1);
+				var service = services[0];
+				c.assertEqual(service.getCode().getPermId(), "simple-service", "Code");
+				c.assertEqual(service.getDescription(), "a simple service", "Description");
+			}
+			
+			testAction(c, fAction, fCheck);
+		})
+		
+		QUnit.test("executeCustomASService()", function(assert){
+			var c = new common(assert);
+			
+			var fAction = function(facade) {
+				var id = new c.CustomASServiceCode("simple-service");
+				var options = new c.CustomASServiceExecutionOptions().withParameter("a", "1").withParameter("space-code", "TEST");
+				return facade.executeCustomASService(id, options);
+			}
+
+			var fCheck = function(facade, result) {
+				c.assertEqual(1, result.getTotalCount());
+				var space = result.getObjects()[0];
+				c.assertEqual(space.getPermId(), "TEST", "PermId");
+				c.assertEqual(space.getCode(), "TEST", "Code");
+				c.assertEqual(space.getDescription(), null, "Description");
+				c.assertDate(space.getRegistrationDate(), "Registration date", 2013, 04, 12, 12, 59);
+			}
+			
+			testAction(c, fAction, fCheck);
+		})
+	}
+})
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASService.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASService.js
index 67e58a7b477bd6429a41c78c864e6d1aa83d9460..cdca7cfd83ce2b3c016f5ad669165ec40ffb41c6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASService.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASService.js
@@ -39,5 +39,5 @@ define([ "stjs", "util/Exceptions" ], function(stjs, exceptions) {
 	}, {
 		fetchOptions : "CustomASServiceFetchOptions"
 	});
-	return Service;
+	return CustomASService;
 })
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASServiceExecutionOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASServiceExecutionOptions.js
index 4320bc7fb3224a013c9afaf1fd94efacda2233b0..c17de38e551725286712b600f4904cebe99e340c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASServiceExecutionOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/service/CustomASServiceExecutionOptions.js
@@ -2,7 +2,7 @@ define([ "stjs"], function(stjs) {
 	var CustomASServiceExecutionOptions = function() {
 		this.parameters = {};
 	};
-	stjs.extend(ExecutionOptions, null, [ ], function(constructor, prototype) {
+	stjs.extend(CustomASServiceExecutionOptions, null, [ ], function(constructor, prototype) {
 		prototype['@type'] = 'as.dto.service.CustomASServiceExecutionOptions';
 		constructor.serialVersionUID = 1;
 		prototype.parameters = null;