diff --git a/plugins/export_ui/services_ctools_export_ui.class.php b/plugins/export_ui/services_ctools_export_ui.class.php
index ab12791..ebe568d 100644
--- a/plugins/export_ui/services_ctools_export_ui.class.php
+++ b/plugins/export_ui/services_ctools_export_ui.class.php
@@ -42,7 +42,7 @@ class services_ctools_export_ui extends ctools_export_ui {
 
   // Avoid standard submit of edit form by ctools.
   function edit_save_form($form_state) { }
-    
+
   function set_item_state($state, $js, $input, $item) {
     ctools_export_set_object_status($item, $state);
 
@@ -264,12 +264,7 @@ function services_edit_form_endpoint_resources($form, &$form_state, $endpoint) {
 
   // Call _services_build_resources() directly instead of
   // services_get_resources to bypass caching.
-  $resources = _services_build_resources();
-
-  // Apply the endpoint in a non-strict mode, so that the non-active resources
-  // are preserved.
-  _services_apply_endpoint($resources, $endpoint, FALSE);
-
+  $resources = _services_build_resources($endpoint->name);
   $form['instructions'] = array(
     '#type' => 'item',
     '#title' => t('Resources'),
@@ -296,6 +291,7 @@ function services_edit_form_endpoint_resources($form, &$form_state, $endpoint) {
     $endpoint->authentication[$module] = $settings;
   }
 
+
   // Generate the list of methods arranged by resource.
   foreach ($resources as $resource_name => $resource) {
     $resource_conf = array();
@@ -319,14 +315,12 @@ function services_edit_form_endpoint_resources($form, &$form_state, $endpoint) {
       '#default_value' => $alias,
       '#size' => 20,
     );
-
     foreach ($class_names as $class => $info) {
       if (!empty($resource[$class])) {
         $res_item[$class] = array(
           '#type' => 'item',
           '#title' => $info['title'],
         );
-
         foreach ($resource[$class] as $op_name => $op) {
           $description = isset($op['help']) ? $op['help'] : t('No description is available');
           $default_value = 0;
@@ -345,6 +339,31 @@ function services_edit_form_endpoint_resources($form, &$form_state, $endpoint) {
           );
 
           $controller_settings = array();
+          // Let modules add their own settings.
+          drupal_alter('controller_settings', $controller_settings);
+          // Get service update versions.
+          $update_versions = services_get_update_versions($resource_name, $op_name);
+          $options = array(
+            '1.0' => '1.0',
+          );
+          $options = array_merge($options, $update_versions);
+          $default_api_value = 0;
+          if (isset($endpoint->resources[$resource_name][$class][$op_name]['settings']['services'])) {
+            $default_api_value = $endpoint->resources[$resource_name][$class][$op_name]['settings']['services'];
+          }
+
+          // Add the version information.
+          $controller_settings['services'] = array(
+            '#title' => 'Services',
+            '#type' => 'item',
+            'resource_api_version' => array(
+              '#type' => 'select',
+              '#options' => $options,
+              '#default_value' => $default_api_value,
+              '#title' => 'Resource API Version',
+              '#disabled' => count($options) == 1 ? TRUE : FALSE,
+            ),
+          );
           foreach ($endpoint->authentication as $module => $settings) {
             $auth_settings = services_auth_invoke($module, 'controller_settings', $settings, $op, $endpoint->authentication[$module], $class, $op_name);
             if (is_array($auth_settings)) {
@@ -400,7 +419,6 @@ function services_edit_form_endpoint_resources_validate($form, $form_state) {
 function services_edit_form_endpoint_resources_submit($form, $form_state) {
   $endpoint  = $form_state['values']['endpoint_object'];
   $resources = $form_state['input']['resources'];
-
   $class_names = services_operation_class_info();
   // Iterate over the resources, its operation classes and operations.
   // The main purpose is to remove empty configuration for disabled elements.
@@ -432,8 +450,32 @@ function services_edit_form_endpoint_resources_submit($form, $form_state) {
       $resources[$resource_name] = $resource;
     }
   }
-
   $endpoint->resources = $resources;
   services_endpoint_save($endpoint);
   drupal_set_message('Resources have been saved');
 }
+
+/**
+ * Returns the updates for a given resource method.
+ *
+ * @param $resource
+ *   A resource name.
+ * @param $method
+ *   A method name.
+ * @return
+ *   an array with the major and minor api versions
+ */
+function services_get_update_versions($resource, $method) {
+  $versions = array();
+  if (variable_get('services_rest_service_versioning_enabled', TRUE) {
+    $updates = services_get_updates();
+    if (isset($updates[$resource][$method]) && is_array($updates[$resource][$method])) {
+      foreach ($updates[$resource][$method] as $update) {
+        extract($update);
+        $value = $major .'.'. $minor;
+        $versions[$value] = $value;
+      }
+    }
+  }
+  return $versions;
+}
diff --git a/resources/file_resource.inc b/resources/file_resource.inc
index 04de1ea..3dc0985 100644
--- a/resources/file_resource.inc
+++ b/resources/file_resource.inc
@@ -368,4 +368,3 @@ function _file_resource_node_access($op = 'view', $args = array()) {
   }
   return FALSE;
 }
-
diff --git a/resources/system_resource.inc b/resources/system_resource.inc
index 5ccf3e3..848927f 100644
--- a/resources/system_resource.inc
+++ b/resources/system_resource.inc
@@ -90,13 +90,10 @@ function _system_resource_definition() {
 function _system_resource_connect() {
   global $user;
   services_remove_user_data($user);
-  
+
   $return = new stdClass();
   $return->sessid = session_id();
   $return->user = $user;
-  
-  
 
   return $return;
 }
-
diff --git a/servers/rest_server/includes/RESTServer.inc b/servers/rest_server/includes/RESTServer.inc
index 281eecf..ab9a695 100755
--- a/servers/rest_server/includes/RESTServer.inc
+++ b/servers/rest_server/includes/RESTServer.inc
@@ -47,7 +47,6 @@ class RESTServer {
     if (empty($response_format)) {
       drupal_add_http_header('Vary', 'Accept');
     }
-
     $endpoint = services_get_server_info('endpoint', '');
     $endpoint_definition = services_endpoint_load($endpoint);
 
@@ -63,7 +62,7 @@ class RESTServer {
       $resource = $resources[$resource_name];
 
       // Get the operation and fill with default values
-      $controller = $this->resolveController($resource, $method, $path);
+      $controller = $this->resolveController($resource, $method, $path, $endpoint_definition, $resource_name);
     }
     else {
       //This will stop the 404 from happening when you request just the endpoint.
@@ -78,6 +77,20 @@ class RESTServer {
     if (!$controller) {
       return services_error(t('Could not find the controller.'), 404);
     }
+    $options = array();
+
+    // If you want version support per request, this must be applied per
+    // server.
+    if (variable_get('services_rest_service_versioning_enabled', TRUE) {
+      foreach(_services_version_header_options() as $key => $version_header_option) {
+        if(array_key_exists($version_header_option, $headers = getallheaders())) {
+          $options['version'] = $headers[$version_header_option];
+        }
+      }
+      $options['resource'] = $resource_name;
+      $options['method'] = $path[0];
+      services_request_apply_version($controller, $options);
+    }
 
     // Parse the request data
     $arguments = $this->getControllerArguments($controller, $path, $method);
@@ -146,7 +159,7 @@ class RESTServer {
     }
 
     try {
-      $result = services_controller_execute($controller, $arguments);
+      $result = services_controller_execute($controller, $arguments, $options);
     }
     catch (ServicesException $e) {
       $errors = $this->handleException($e);
@@ -247,7 +260,9 @@ class RESTServer {
     switch ($method) {
       case 'POST':
       case 'PUT':
-        $type = self::parseContentHeader($_SERVER['CONTENT_TYPE']);
+        if (isset($_SERVER['CONTENT_TYPE'])) {
+          $type = self::parseContentHeader($_SERVER['CONTENT_TYPE']);
+        }
 
         // Get the mime type for the request, default to form-urlencoded
         if (isset($type['value'])) {
@@ -506,7 +521,7 @@ class RESTServer {
     }
   }
 
-  private function resolveController($resource, $method, $path) {
+  private function resolveController($resource, $method, $path, $endpoint, $resource_name) {
     $pc = count($path);
     $class = NULL;
     $operation = NULL;
diff --git a/services.module b/services.module
index 4830c7a..59fa586 100644
--- a/services.module
+++ b/services.module
@@ -464,6 +464,150 @@ function services_controller_get($name, $endpoint) {
     }
   }
 }
+/**
+ * Returns an array of available updates versions for a resource.
+ *
+ * @return
+ *   If services has updates, an array of available updates sorted by version.
+ *   Otherwise, FALSE.
+ */
+function services_get_updates() {
+  $updates = &drupal_static(__FUNCTION__, NULL);
+  if (!isset($updates)) {
+    $updates = array();
+    module_load_include('resource_build.inc', 'services');
+    // Load the resources for services.
+    _services_core_resources();
+    // Prepare regular expression to match all possible defined
+    // _resource_resource_method_update_N_N().
+    $regexp = '/_(?P<resource>.+)_resource_(?P<method>.+)_update_(?P<major>\d+)_(?P<minor>\d+)$/';
+    $functions = get_defined_functions();
+    // Narrow this down to functions ending with an integer, since all
+    // _resource_resource_method_update_N_N() functions end this way, and there are other
+    // possible functions which match '_update_'. We use preg_grep() here
+    // instead of foreaching through all defined functions, since the loop
+    // through all PHP functions can take significant page execution time.
+    // Luckily this only happens when the cache is cleared for an endpoint
+    // and resources are re-generated.
+    foreach (preg_grep('/_\d+$/', $functions['user']) as $function) {
+      // If this function is a service update function, add it to the list of
+      // services updates.
+      if (preg_match($regexp, $function, $matches)) {
+        extract($matches);
+        $updates[$resource][$method][] = array(
+          'version'  => $major .'_'. $minor,
+          'major'    => $major,
+          'minor'    => $minor,
+          'callback' => $function,
+          'resource' => $resource,
+          'method'   => $method,
+        );
+      }
+    }
+  }
+  return empty($updates) ? FALSE : $updates;
+}
+
+/**
+ * Returns currently set api version for an endpoint resource method.
+ *
+ * @param $endpoint
+ *   A fully loadded endpoint.
+ * @param $resource
+ *   A resource name.
+ * @param $method
+ *   A method name.
+ * @return
+ *   an array with the major and minor api versions
+ */
+function services_get_resource_api_version($endpoint, $resource, $method) {
+  if (isset($endpoint->resources[$resource]) ) {
+    $class_info = services_operation_class_info();
+    foreach ($class_info as $class_name => $class) {
+      if (!empty($resource[$class_name])) {
+        if (isset($endpoint->resources[$resource][$class_name][$method]['settings']['services']['resource_api_version'])) {
+          $split = explode('.', $endpoint->resources[$resource][$class_name][$method]['settings']['services']['resource_api_version']);
+          return array(
+            'major' => $split[0],
+            'minor' => $split[1],
+          );
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Apply versions to the controller.
+ *
+ * @param $controller
+ *   A controller array.
+ * @param $options
+ *   A options array filled with verison information.
+ * @return
+ *   An array with the major and minor api versions
+ */
+function services_request_apply_version(&$controller, $options = array()) {
+  if (isset($options)) {
+    extract($options);
+  }
+  if (isset($version) && $version == '1.0') {
+    $controller = $controller['original'];
+  }
+  $updates = services_get_updates();
+  if (isset($updates[$resource][$method])) {
+    foreach ($updates[$resource][$method] as $update) {
+      if (!isset($version)) {
+        $endpoint = services_get_server_info('endpoint', '');
+        $default_version = services_get_resource_api_version($endpoint, $resource, $method);
+      }
+      else {
+        $default_version = explode('.', $version);
+        $default_version['major'] = $default_version[0];
+        $default_version['minor'] = $default_version[1];
+      }
+      // Apply updates until we hit our default update for the site.
+      if ($default_version['major'] == $update['major'] && $default_version['minor'] == $update['minor']) {
+        $update_data = call_user_func($update['callback']);
+        $controller = array_merge($controller, $update_data);
+      }
+    }
+  }
+}
+
+/**
+ * Applies version information to our controller.
+ *
+ * @param $controllers
+ *   A fully loadded endpoint.
+ * @param $resource
+ *   A resource name.
+ * @param $method
+ *   A method name.
+ * @return
+ *   An array with the major and minor api versions.
+ */
+function services_controllers_apply_version($controllers, $endpoint) {
+  $updates = services_get_updates();
+  // Loop through all of our controllers.
+  // @todo make it so the updates only apply based on endpoint settings;
+  foreach ($controllers as $key => &$controller) {
+    list($resource, $op, $method)  = explode('/', $key);
+    // If we found a match, and its an array call the callback function.
+    if (isset($updates[$resource][$method]) && is_array($updates[$resource][$method])) {
+      foreach ($updates[$resource][$method] as $update) {
+        // Apply updates until we hit our default update for the site.
+        $default_version = services_get_resource_api_version($endpoint, $resource, $method);
+        if ($default_version['major'] == $update['major'] && $default_version['minor'] == $update['minor']) {
+          $update_data = call_user_func($update['callback']);
+          $old_controller = $controller;
+          $controller = array_merge($controller, $update_data);
+          $controller['original'] = $old_controller;
+        }
+      }
+    }
+  }
+}
 
 /**
  * Convert a resource to RPC-style methods.
diff --git a/services.resource_build.inc b/services.resource_build.inc
index b822c4c..07057db 100644
--- a/services.resource_build.inc
+++ b/services.resource_build.inc
@@ -28,7 +28,7 @@ function _services_build_resources($endpoint_name = '') {
       continue;
     }
 
-    // Check resource versions
+    // Check resource versions.
     $api_version = $version_info['default_version'];
     if (!empty($module_resources['#api_version'])) {
       $api_version = $module_resources['#api_version'];
@@ -42,16 +42,14 @@ function _services_build_resources($endpoint_name = '') {
     $resources = array_merge($resources, $module_resources);
   }
 
-  // Load the endpoint
+  // Load the endpoint.
   $endpoint = NULL;
   if (!empty($endpoint_name)) {
     $endpoint = services_endpoint_load($endpoint_name);
     // Apply the endpoint on the services
-    _services_apply_endpoint($resources, $endpoint, TRUE);
+    _services_apply_endpoint($resources, $endpoint, FALSE);
   }
-
   drupal_alter('services_resources', $resources, $endpoint);
-
   // Process the resources, and collect all controllers in the process
   $controllers = array();
   $class_info = services_operation_class_info();
@@ -79,13 +77,12 @@ function _services_build_resources($endpoint_name = '') {
       $controller['access callback'] = 'user_access';
     }
   }
-  drupal_alter('services_resources_controller_post_processing', $controllers, $endpoint);
-
+  services_controllers_apply_version($controllers, $endpoint);
   // This hook is deprecated and will be removed in next versions of services.
   // Use hook_services_resources_alter instead.
   drupal_alter('services_resources_post_processing', $resources, $endpoint);
 
-  // Do some endpoint-dependent processing
+  // Do some endpoint-dependent processing.
   if ($endpoint) {
     // Let the authentication modules alter our controllers
     foreach ($endpoint->authentication as $auth_module => $auth_settings) {
diff --git a/services.runtime.inc b/services.runtime.inc
index db25f2b..d03c8a8 100644
--- a/services.runtime.inc
+++ b/services.runtime.inc
@@ -80,6 +80,18 @@ class ServicesArgumentException extends ServicesException {
 }
 
 /**
+ * Determine if any potential versions exist as valid headers.
+ */
+function _services_version_header_options() {
+  $available_headers = array();
+  foreach (services_get_updates() as $resource => $update) {
+    foreach ($update as $method_name => $method) {
+      $available_headers[] = 'services_'. $resource .'_'.$method_name .'_version';
+    }
+  }
+  return $available_headers;
+}
+/**
  * Performs access checks and executes a services controller.
  * This method is called by server implementations.
  *
@@ -106,19 +118,17 @@ function services_controller_execute($controller, $args = array(), $options = ar
   $user = drupal_anonymous_user();
   $user->timestamp = time();
   services_set_server_info('original_user', $original_user);
+  $endpoint_name = services_get_server_info('endpoint');
+  $endpoint = services_endpoint_load($endpoint_name);
 
   // Check authentication.
   if (!isset($options['skip_authentication']) || !$options['skip_authentication']) {
-    $endpoint_name = services_get_server_info('endpoint');
-    $endpoint = services_endpoint_load($endpoint_name);
-
     foreach ($endpoint->authentication as $auth_module => $settings) {
       if (isset($settings) && $auth_error = services_auth_invoke($auth_module, 'authenticate_call', $settings, $controller, $args)) {
         return services_error($auth_error, 401);
       }
     }
   }
-
   // Load the proper file.
   if (!empty($controller['file']) && $file = $controller['file']) {
     module_load_include($file['type'], $file['module'], (isset($file['name']) ? $file['name'] : NULL));
@@ -149,7 +159,8 @@ function services_controller_execute($controller, $args = array(), $options = ar
     )), 401);
   }
 
-  drupal_alter('services_request_preprocess', $controller, $args);
+
+  drupal_alter('services_request_preprocess', $controller, $args, $options);
 
   // Log the arguments.
   if ($server_info->debug) {
@@ -158,12 +169,12 @@ function services_controller_execute($controller, $args = array(), $options = ar
 
   // Execute the controller callback.
   $result = call_user_func_array($controller['callback'], $args);
-  
+
   drupal_alter('services_request_postprocess', $controller, $args, $result);
-  
+
   if (drupal_save_session($user) === FALSE) {
     $user = $original_user;
-    drupal_save_session($old_state);  
+    drupal_save_session($old_state);
   }
   if ($server_info->debug) {
     watchdog('services', 'results: <pre>@results</pre>', array('@results' => print_r($result, TRUE)), WATCHDOG_DEBUG);
diff --git a/services.versions.api.php b/services.versions.api.php
new file mode 100644
index 0000000..0689374
--- /dev/null
+++ b/services.versions.api.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @file
+ * Explains how to use versions
+ */
+
+/*
+ * All functions that want to be considered for updates need to use a specific naming convetion
+ * WE took the same approach as the standard Drupal hook_instal and .install methods.
+ * For clients that want to request a specific version they need to pass a certain header
+ * services_RESOURCE_METHOD_version = version
+ * as an example, services_system_set_variable_version = 1.2
+ * Services by default will always use the originl resource shipped
+ * with services. If you wish to change this you can goto the resource page,
+ * and select an api version for the specific resource. The version option will
+ * only be enabled if version changes exists
+ *
+ */
+
+
+
+function _system_resource_set_variable_update_1_1() {
+  $new_set = array(
+    'help' => 'Create a node with an nid test',
+  );
+  return $new_set;
+}
+function _system_resource_set_variable_update_1_2() {
+  $new_set = array(
+    'help' => 'Create a node with an nid optional prams.',
+    'args' => array(
+      array(
+        'name' => 'name',
+        'optional' => TRUE,
+        'source' => array('data' => 'name'),
+        'description' => t('The name of the variable to set.'),
+        'type' => 'string',
+      ),
+      array(
+        'name' => 'value',
+        'optional' => TRUE,
+        'source' => array('data' => 'value'),
+        'description' => t('The value to set.'),
+        'type' => 'string',
+      ),
+    ),
+  );
+  return $new_set;
+}
