diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php
index da17a7f2ccd26d5dbb2a7479999b60510eedbd36..6535a9b7baa39023f8ed10278898aea778d8fd4e 100644
--- a/apps/files/appinfo/app.php
+++ b/apps/files/appinfo/app.php
@@ -1,4 +1,6 @@
 <?php
+OC::$CLASSPATH['OCA\Files\Capabilities'] = 'apps/files/lib/capabilities.php';
+
 $l = OC_L10N::get('files');
 
 OCP\App::registerAdmin('files', 'admin');
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php
index 043782a9c04c5cdb5cb9958b0b848ba6f8994f93..fcd5f4b2608d9d51b45edce8ff1faac4eef1c03d 100644
--- a/apps/files/appinfo/routes.php
+++ b/apps/files/appinfo/routes.php
@@ -8,4 +8,7 @@
 
 $this->create('download', 'download{file}')
 	->requirements(array('file' => '.*'))
-	->actionInclude('files/download.php');
\ No newline at end of file
+	->actionInclude('files/download.php');
+	
+// Register with the capabilities API
+OC_API::register('get', '/cloud/capabilities', array('OCA\Files\Capabilities', 'getCapabilities'), 'files', OC_API::USER_AUTH);
\ No newline at end of file
diff --git a/apps/files/lib/capabilities.php b/apps/files/lib/capabilities.php
new file mode 100644
index 0000000000000000000000000000000000000000..90a5e2f4eb900a8650b9819c02c43bcdf6c521bf
--- /dev/null
+++ b/apps/files/lib/capabilities.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Copyright (c) 2013 Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+ 
+namespace OCA\Files; 
+
+class Capabilities {
+	
+	public static function getCapabilities() {
+		return new \OC_OCS_Result(array(
+			'capabilities' => array(
+				'files' => array(
+					'bigfilechunking' => true,
+					'undelete' => true,
+					),
+				),
+			));
+	}
+	
+}
\ No newline at end of file
diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php
index f7b2140b580afa15b02923ec1f3ac0d8f91b5e5e..bf16fec3aea0d60678d0a26d8121c9cbd0413868 100644
--- a/apps/files_encryption/appinfo/app.php
+++ b/apps/files_encryption/appinfo/app.php
@@ -7,6 +7,7 @@ OC::$CLASSPATH['OCA\Encryption\Keymanager'] = 'files_encryption/lib/keymanager.p
 OC::$CLASSPATH['OCA\Encryption\Stream'] = 'files_encryption/lib/stream.php';
 OC::$CLASSPATH['OCA\Encryption\Proxy'] = 'files_encryption/lib/proxy.php';
 OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php';
+OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php';
 
 OC_FileProxy::register( new OCA\Encryption\Proxy() );
 
diff --git a/apps/files_encryption/appinfo/routes.php b/apps/files_encryption/appinfo/routes.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab83432a4b2d5a84188c862dbdc61a1faf30ea9a
--- /dev/null
+++ b/apps/files_encryption/appinfo/routes.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Copyright (c) 2013, Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+// Register with the capabilities API
+OC_API::register('get', '/cloud/capabilities', array('OCA\Encryption\Capabilities', 'getCapabilities'), 'files_encryption', OC_API::USER_AUTH);
\ No newline at end of file
diff --git a/apps/files_encryption/lib/capabilities.php b/apps/files_encryption/lib/capabilities.php
new file mode 100644
index 0000000000000000000000000000000000000000..72baddcd0495f2197592b8f53cde23bfaca54507
--- /dev/null
+++ b/apps/files_encryption/lib/capabilities.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) 2013 Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+ 
+namespace OCA\Encryption; 
+
+class Capabilities {
+	
+	public static function getCapabilities() {
+		return new \OC_OCS_Result(array(
+			'capabilities' => array(
+				'files' => array(
+					'encryption' => true,
+					),
+				),
+			));
+	}
+	
+}
\ No newline at end of file
diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php
index 44d01f5cd5e893d8e62d3010fd6db638301f43cf..9be1c88968249a40398c31259fd7a61929b7dc91 100644
--- a/apps/files_versions/appinfo/app.php
+++ b/apps/files_versions/appinfo/app.php
@@ -3,6 +3,7 @@
 //require_once 'files_versions/versions.php';
 OC::$CLASSPATH['OCA\Files_Versions\Storage'] = 'files_versions/lib/versions.php';
 OC::$CLASSPATH['OCA\Files_Versions\Hooks'] = 'files_versions/lib/hooks.php';
+OC::$CLASSPATH['OCA\Files_Versions\Capabilities'] = 'files_versions/lib/capabilities.php';
 
 OCP\Util::addscript('files_versions', 'versions');
 
diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php
new file mode 100644
index 0000000000000000000000000000000000000000..8cef57c9e4dd723e0d81e1643a8c6d2207e21272
--- /dev/null
+++ b/apps/files_versions/appinfo/routes.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Copyright (c) 2013, Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+// Register with the capabilities API
+OC_API::register('get', '/cloud/capabilities', array('OCA\Files_Versions\Capabilities', 'getCapabilities'), 'files_versions', OC_API::USER_AUTH);
\ No newline at end of file
diff --git a/apps/files_versions/lib/capabilities.php b/apps/files_versions/lib/capabilities.php
new file mode 100644
index 0000000000000000000000000000000000000000..3251a07b6ae204f1af5a58cc876f9f38b50765a2
--- /dev/null
+++ b/apps/files_versions/lib/capabilities.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) 2013 Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+ 
+namespace OCA\Files_Versions; 
+
+class Capabilities {
+	
+	public static function getCapabilities() {
+		return new \OC_OCS_Result(array(
+			'capabilities' => array(
+				'files' => array(
+					'versioning' => true,
+					),
+				),
+			));
+	}
+	
+}
\ No newline at end of file
diff --git a/lib/api.php b/lib/api.php
index 70e3028b68a95cfef127b71a6d990ce5a774acec..8d6bbb7cc09631f038d9beca6bcae25e123c7ad0 100644
--- a/lib/api.php
+++ b/lib/api.php
@@ -33,21 +33,20 @@ class OC_API {
 	const USER_AUTH = 1;
 	const SUBADMIN_AUTH = 2;
 	const ADMIN_AUTH = 3;
-
-	private static $server;
-
+	
 	/**
-	 * initialises the OAuth store and server
+	 * API Response Codes
 	 */
-	private static function init() {
-		self::$server = new OC_OAuth_Server(new OC_OAuth_Store());
-	}
-
+	const RESPOND_UNAUTHORISED = 997;
+	const RESPOND_SERVER_ERROR = 996;
+	const RESPOND_NOT_FOUND = 998;
+	const RESPOND_UNKNOWN_ERROR = 999;
+	
 	/**
 	 * api actions
 	 */
 	protected static $actions = array();
-
+	
 	/**
 	 * registers an api call
 	 * @param string $method the http method
@@ -58,7 +57,7 @@ class OC_API {
 	 * @param array $defaults
 	 * @param array $requirements
 	 */
-	public static function register($method, $url, $action, $app,
+	public static function register($method, $url, $action, $app, 
 				$authLevel = OC_API::USER_AUTH,
 				$defaults = array(),
 				$requirements = array()) {
@@ -71,9 +70,9 @@ class OC_API {
 				->action('OC_API', 'call');
 			self::$actions[$name] = array();
 		}
-		self::$actions[$name] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
+		self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel);
 	}
-
+	
 	/**
 	 * handles an api call
 	 * @param array $parameters
@@ -86,29 +85,97 @@ class OC_API {
 			parse_str(file_get_contents("php://input"), $parameters['_delete']);
 		}
 		$name = $parameters['_route'];
-		// Check authentication and availability
-		if(self::isAuthorised(self::$actions[$name])) {
-			if(is_callable(self::$actions[$name]['action'])) {
-				$response = call_user_func(self::$actions[$name]['action'], $parameters);
-				if(!($response instanceof OC_OCS_Result)) {
-					$response = new OC_OCS_Result(null, 996, 'Internal Server Error');
-				}
-			} else {
-				$response = new OC_OCS_Result(null, 998, 'Api method not found');
+		// Foreach registered action
+		$responses = array();
+		foreach(self::$actions[$name] as $action) {
+			// Check authentication and availability
+			if(!self::isAuthorised(self::$actions[$name])) {
+				$responses[] = array(
+					'app' => $action['app'],
+					'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'),
+					);
+				continue;
 			}
-		} else {
-			header('WWW-Authenticate: Basic realm="Authorization Required"');
-			header('HTTP/1.0 401 Unauthorized');
-			$response = new OC_OCS_Result(null, 997, 'Unauthorised');
+			if(!is_callable($action['action'])) {
+				$responses[] = array(
+					'app' => $action['app'],
+					'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'),
+					);
+				continue;
+			}
+			// Run the action
+			$responses[] = array(
+				'app' => $action['app'],
+				'response' => call_user_func($action['action'], $parameters),
+				);
 		}
-		// Send the response
+		$response = self::mergeResponses($responses);
 		$formats = array('json', 'xml');
 		$format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml';
-		self::respond($response, $format);
-		// logout the user to be stateless
+		self::respond($response);
 		OC_User::logout();
 	}
+	
+	/**
+	 * merge the returned result objects into one response
+	 * @param array $responses
+	 */
+	private static function mergeResponses($responses) {
+		$response = array();
+		// Sort into shipped and thirdparty
+		$shipped = array(
+			'succeeded' => array(),
+			'failed' => array(),
+			);
+		$thirdparty = array(
+			'succeeded' => array(),
+			'failed' => array(),
+			);
 
+		foreach($responses as $response) {
+			if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) {
+				if($response['response']->succeeded()) {
+					$shipped['succeeded'][$response['app']] = $response['response'];
+				} else {
+					$shipped['failed'][$response['app']] = $response['response'];
+				}
+			} else {
+				if($response['response']->succeeded()) {
+					$thirdparty['succeeded'][$response['app']] = $response['response'];
+				} else {
+					$thirdparty['failed'][$response['app']] = $response['response'];
+				}
+			}
+		}
+		// Remove any error responses if there is one shipped response that succeeded
+		if(!empty($shipped['succeeded'])) {
+			$responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
+		} else if(!empty($shipped['failed'])) {
+			// Which shipped response do we use if they all failed?
+			// They may have failed for different reasons (different status codes)
+			// Which reponse code should we return?
+			// Maybe any that are not OC_API::RESPOND_SERVER_ERROR
+			$response = $shipped['failed'][0];
+			return $response;
+		} else {
+			// Return the third party failure result
+			$response = $thirdparty['failed'][0];
+			return $response;
+		}
+		// Merge the successful responses
+		$meta = array();
+		$data = array();
+		foreach($responses as $app => $response) {
+			if(OC_App::isShipped($app)) {
+				$data = array_merge_recursive($response->getData(), $data);
+			} else {
+				$data = array_merge_recursive($data, $response->getData());
+			}
+		}
+		$result = new OC_OCS_Result($data, 100);
+		return $result;
+	}
+	
 	/**
 	 * authenticate the api call
 	 * @param array $action the action details as supplied to OC_API::register()
@@ -132,7 +199,8 @@ class OC_API {
 					return false;
 				} else {
 					$subAdmin = OC_SubAdmin::isSubAdmin($user);
-					if($subAdmin) {
+					$admin = OC_User::isAdminUser($user);
+					if($subAdmin || $admin) {
 						return true;
 					} else {
 						return false;
@@ -153,25 +221,35 @@ class OC_API {
 				return false;
 				break;
 		}
-	}
-
+	} 
+	
 	/**
 	 * http basic auth
 	 * @return string|false (username, or false on failure)
 	 */
-	private static function loginUser(){
+	private static function loginUser(){ 
 		$authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
 		$authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
 		return OC_User::login($authUser, $authPw) ? $authUser : false;
 	}
-
+	
 	/**
 	 * respond to a call
-	 * @param int|array $result the result from the api method
+	 * @param OC_OCS_Result $result
 	 * @param string $format the format xml|json
 	 */
 	private static function respond($result, $format='xml') {
-		$response = array('ocs' => $result->getResult());
+		// Send 401 headers if unauthorised
+		if($result->getStatusCode() === self::RESPOND_UNAUTHORISED) {
+			header('WWW-Authenticate: Basic realm="Authorisation Required"');
+			header('HTTP/1.0 401 Unauthorized');
+		}
+		$response = array(
+			'ocs' => array(
+				'meta' => $result->getMeta(),
+				'data' => $result->getData(),
+				),
+			);
 		if ($format == 'json') {
 			OC_JSON::encodedPrint($response);
 		} else if ($format == 'xml') {
@@ -203,5 +281,5 @@ class OC_API {
 			}
 		}
 	}
-
+	
 }
diff --git a/lib/ocs/cloud.php b/lib/ocs/cloud.php
index 5553ae382151d50b936a4b8ab32ca58323b21a2b..132d923d960ef42b5e3d52e6f77a0e05e7e19b26 100644
--- a/lib/ocs/cloud.php
+++ b/lib/ocs/cloud.php
@@ -24,49 +24,23 @@
 
 class OC_OCS_Cloud {
 
-	public static function getSystemWebApps() {
-		OC_Util::checkLoggedIn();
-		$apps = OC_App::getEnabledApps();
-		$values = array();
-		foreach($apps as $app) {
-			$info = OC_App::getAppInfo($app);
-			if(isset($info['standalone'])) {
-				$newValue = array('name'=>$info['name'], 'url'=>OC_Helper::linkToAbsolute($app, ''), 'icon'=>'');
-				$values[] = $newValue;
-			}
-		}
-		return new OC_OCS_Result($values);
-	}
-
-	public static function getUserQuota($parameters) {
-		$user = OC_User::getUser();
-		if(OC_User::isAdminUser($user) or ($user==$parameters['user'])) {
-
-			if(OC_User::userExists($parameters['user'])) {
-				// calculate the disc space
-				$userDir = '/'.$parameters['user'].'/files';
-				\OC\Files\Filesystem::init($parameters['user'], $userDir);
-				$rootInfo = \OC\Files\Filesystem::getFileInfo('');
-				$sharedInfo = \OC\Files\Filesystem::getFileInfo('/Shared');
-				$used = $rootInfo['size'] - $sharedInfo['size'];
-				$free = \OC\Files\Filesystem::free_space();
-				$total = $free + $used;
-				if($total===0) $total = 1;  // prevent division by zero
-				$relative = round(($used/$total)*10000)/100;
-
-				$xml = array();
-				$xml['quota'] = $total;
-				$xml['free'] = $free;
-				$xml['used'] = $used;
-				$xml['relative'] = $relative;
-
-				return new OC_OCS_Result($xml);
-			} else {
-				return new OC_OCS_Result(null, 300);
-			}
-		} else {
-			return new OC_OCS_Result(null, 300);
-		}
+	public static function getCapabilities($parameters) {
+		$result = array();
+		list($major, $minor, $micro) = OC_Util::getVersion();
+		$result['version'] = array(
+			'major' => $major,
+			'minor' => $minor,
+			'micro' => $micro,
+			'string' => OC_Util::getVersionString(),
+			'edition' => OC_Util::getEditionString(),
+			);
+			
+			$result['capabilities'] = array(
+				'core' => array(
+					'pollinterval' => OC_Config::getValue('pollinterval', 60),
+					),
+				);
+		return new OC_OCS_Result($result);
 	}
 
 	public static function getUserPublickey($parameters) {
diff --git a/lib/ocs/result.php b/lib/ocs/result.php
index 65b2067fc3f2ecfa6f5cb5d92b94706c9ff0dae5..8ab378d79c530091387f0c61ab393c68243a1620 100644
--- a/lib/ocs/result.php
+++ b/lib/ocs/result.php
@@ -49,26 +49,48 @@ class OC_OCS_Result{
 	public function setItemsPerPage(int $items) {
 		$this->perPage = $items;
 	}
-
+	
+	/**
+	 * get the status code
+	 * @return int
+	 */
+	public function getStatusCode() {
+		return $this->statusCode;
+	}
+	
 	/**
-	 * returns the data associated with the api result
+	 * get the meta data for the result
 	 * @return array
 	 */
-	public function getResult() {
-		$return = array();
-		$return['meta'] = array();
-		$return['meta']['status'] = ($this->statusCode === 100) ? 'ok' : 'failure';
-		$return['meta']['statuscode'] = $this->statusCode;
-		$return['meta']['message'] = $this->message;
+	public function getMeta() {
+		$meta = array();
+		$meta['status'] = ($this->statusCode === 100) ? 'ok' : 'failure';
+		$meta['statuscode'] = $this->statusCode;
+		$meta['message'] = $this->message;
 		if(isset($this->items)) {
-			$return['meta']['totalitems'] = $this->items;
+			$meta['totalitems'] = $this->items;
 		}
 		if(isset($this->perPage)) {
-			$return['meta']['itemsperpage'] = $this->perPage;
+			$meta['itemsperpage'] = $this->perPage;
 		}
-		$return['data'] = $this->data;
-		// Return the result data.
-		return $return;
+		return $meta;
+
+	}
+	
+	/**
+	 * get the result data
+	 * @return array|string|int 
+	 */
+	public function getData() {
+		return $this->data;
+	}
+	
+	/**
+	 * return bool if the method succedded
+	 * @return bool
+	 */
+	public function succeeded() {
+		return (substr($this->statusCode, 0, 1) === '1');
 	}
 
 
diff --git a/ocs/routes.php b/ocs/routes.php
index d6ee589df6ffe593f73dbd5b8c319d546334b14a..81beae2f88104988481bdca6e90e4628b6eff37a 100644
--- a/ocs/routes.php
+++ b/ocs/routes.php
@@ -17,4 +17,5 @@ OC_API::register('get', '/privatedata/getattribute/{app}', array('OC_OCS_Private
 OC_API::register('get', '/privatedata/getattribute/{app}/{key}', array('OC_OCS_Privatedata', 'get'), 'ocs', OC_API::USER_AUTH);
 OC_API::register('post', '/privatedata/setattribute/{app}/{key}', array('OC_OCS_Privatedata', 'set'), 'ocs', OC_API::USER_AUTH);
 OC_API::register('post', '/privatedata/deleteattribute/{app}/{key}', array('OC_OCS_Privatedata', 'delete'), 'ocs', OC_API::USER_AUTH);
-
+// cloud
+OC_API::register('get', '/cloud/capabilities', array('OC_OCS_Cloud', 'getCapabilities'), 'core', OC_API::USER_AUTH);
\ No newline at end of file