diff --git a/prepopulate.module b/prepopulate.module
index af9c21a..043b526 100644
--- a/prepopulate.module
+++ b/prepopulate.module
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Fill form elements with data from GET or POST values.
+ * Fill form elements with data from GET, POST values or from external modules.
  *
  * Originally written by ea. Farris <eafarris@gmail.com>
  * Based on an idea from chx, from the conversation at
@@ -24,27 +24,44 @@ function prepopulate_help($path, $arg) {
  * Implementation of hook_form_alter().
  */
 function prepopulate_form_alter(&$form, $form_state, $form_id) {
+  $data = _prepopulate_get_data();
+  if (!empty($data)) {
+    $form['#after_build'][] = 'prepopulate_after_build';
+  }
+}
+
+/**
+ * Implementation of hook_prepopulate().
+ */
+function prepopulate_prepopulate() {
+  $request = array();
   // Provide for accepting base64 encoded fields.
   if (isset($_REQUEST['pp'])) {
     parse_str(base64_decode($_REQUEST['pp']), $_REQUEST);
   } 
   if (isset($_REQUEST['edit'])) {
-    $form['#after_build'][] = 'prepopulate_after_build';
+    $request = (array)$_REQUEST['edit'];
   }
+  return $request;
 }
 
 /**
  * An #after_build function to set the values prepopulated in the request.
  */
 function prepopulate_after_build($form, &$form_state) {
-  if (isset($_REQUEST['pp'])) {
-    parse_str(base64_decode($_REQUEST['pp']), $_REQUEST);
+  _prepopulate_request_walk($form, _prepopulate_get_data());
+  return $form;
   }
-  if (isset($_REQUEST['edit'])) {
-    $request = (array)$_REQUEST['edit'];
-    _prepopulate_request_walk($form, $request);
+
+/**
+ * Returns the data to prepopulate
+ */
+function _prepopulate_get_data() {
+  static $data = FALSE;
+  if ($data === FALSE) {
+    $data = module_invoke_all('prepopulate');
   }
-  return $form;
+  return $data;
 }
 
 /**
