diff --git a/flag.info.inc b/flag.info.inc
new file mode 100644
index 0000000..1870c5a
--- /dev/null
+++ b/flag.info.inc
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file Contains Entity API property information.
+ */
+
+/**
+ * Implements hook_entity_property_info_alter().
+ *
+ * We add properties thus:
+ *  - global flags:
+ *    - entity->flag_FLAGNAME, boolean.
+ *  - per-user flags:
+ *    - entity->flag_FLAGNAME_users, list of users.
+ *    - user->flag_FLAGNAME_flagged, list of user's flagged entities.
+ */
+function flag_entity_property_info_alter(&$info) {
+  foreach (flag_get_flags() as $flag) {
+    if ($flag->global) {
+      // Global flags.
+      // Boolean property on entity type.
+      // This can go on either the entity as a whole, or on bundles, depending
+      // on whether the flag is limited by bundle.
+      $property_definition = array(
+        'label' => t('Whether the entity is flagged with flag @flag', array(
+          '@flag' => $flag->name,
+        )),
+        'description' => t('Whether the entity is flagged with flag @flag.', array(
+          '@flag' => $flag->name,
+        )),
+        'type' => 'boolean',
+        'getter callback' => 'flag_properties_get_flagging_boolean',
+        'computed' => TRUE,
+        'flag_name' => $flag->name,
+      );
+      if (count($flag->types)) {
+        // Bundle specific property.
+        foreach ($flag->types as $type) {
+          $info[$flag->entity_type]['bundles'][$type]['properties']['flag_' . $flag->name] = $property_definition;
+        }
+      }
+      else {
+        // Generic property, applies for all bundles.
+        $info[$flag->entity_type]['properties']['flag_' . $flag->name] = $property_definition;
+      }
+    }
+    else {
+      // Per-user flags.
+      // User property: list of flagged entities by the user.
+      $info['user']['properties']['flag_' . $flag->name . '_flagged'] = array(
+        'label' => t('Flagged @entity-type with flag @flag', array(
+          '@entity-type' => $flag->entity_type,
+          '@flag' => $flag->name,
+        )),
+        'description' => t('Returns a list of entities a user flagged with flag @flag.', array(
+          '@flag' => $flag->name,
+        )),
+        'type' => 'list<' . $flag->entity_type . '>',
+        'getter callback' => 'flag_properties_get_flagged_entities',
+        'computed' => TRUE,
+        'flag_name' => $flag->name,
+        'flag_entity_type' => $flag->entity_type,
+      );
+      // Entity property: list of users who have flagged this entity.
+      // This can go on either the entity as a whole, or on bundles, depending
+      // on whether the flag is limited by bundle.
+      $property_definition = array(
+        'label' => t('Users who flagged the entity with flag @flag', array(
+          '@flag' => $flag->name,
+        )),
+        'description' => t('Returns a list of users who flagged an entity with flag @flag.', array(
+          '@flag' => $flag->name,
+        )),
+        'type' => 'list<user>',
+        'getter callback' => 'flag_properties_get_flagging_users',
+        'computed' => TRUE,
+        'flag_name' => $flag->name,
+      );
+      if (count($flag->types)) {
+        // Bundle specific property.
+        foreach ($flag->types as $type) {
+          $info[$flag->entity_type]['bundles'][$type]['properties']['flag_' . $flag->name . '_user'] = $property_definition;
+        }
+      }
+      else {
+        // Generic property, applies for all bundles.
+        $info[$flag->entity_type]['properties']['flag_' . $flag->name . '_user'] = $property_definition;
+      }
+    }
+  }
+}
diff --git a/flag.module b/flag.module
index 85927b6..adedfbf 100644
--- a/flag.module
+++ b/flag.module
@@ -2343,3 +2343,43 @@ function flag_ctools_plugin_directory($module, $plugin) {
     return "plugins/$plugin";
   }
 }
+
+// ---------------------------------------------------------------------------
+// Entity Metadata callbacks
+
+/**
+ * Getter callback that returns whether the given entity is flagged.
+ */
+function flag_properties_get_flagging_boolean($entity, array $options, $name, $entity_type, $property_info) {
+  list($entity_id,) = entity_extract_ids($entity_type, $entity);
+
+  $flagging_data = flag_get_user_flags($entity_type, $entity_id);
+  return isset($flagging_data[$property_info['flag_name']]);
+}
+
+/**
+ * Getter callback that returns entities the given user flagged.
+ */
+function flag_properties_get_flagged_entities($entity, array $options, $name, $entity_type, $property_info) {
+  // Need the entity type the flag applies to.
+  $flag_entity_type = $property_info['flag_entity_type'];
+
+  $flagging_data = flag_get_user_flags($flag_entity_type, NULL, $entity->uid);
+
+  $flag_name = $property_info['flag_name'];
+  if (isset($flagging_data[$flag_name])) {
+    return array_keys($flagging_data[$flag_name]);
+  }
+  return array();
+}
+
+/**
+ * Getter callback that returns users who flagged the given entity.
+ */
+function flag_properties_get_flagging_users($entity, array $options, $name, $entity_type, $property_info) {
+  list($entity_id,) = entity_extract_ids($entity_type, $entity);
+
+  $flagging_data = flag_get_entity_flags($entity_type, $entity_id, $property_info['flag_name']);
+
+  return array_keys($flagging_data);
+}
