diff --git a/flag.info b/flag.info
index 90bbfb1..59b1bed 100644
--- a/flag.info
+++ b/flag.info
@@ -15,6 +15,7 @@ files[] = includes/flag.cookie_storage.inc
 
 files[] = includes/flag.entity.inc
 files[] = flag.rules.inc
+files[] = flag.migrate.inc
 
 ; Views
 files[] = includes/views/flag_handler_argument_entity_id.inc
diff --git a/flag.migrate.inc b/flag.migrate.inc
new file mode 100644
index 0000000..e52621d
--- /dev/null
+++ b/flag.migrate.inc
@@ -0,0 +1,204 @@
+<?php
+
+/**
+ * @file
+ * Migrate integration for flag module
+ */
+
+
+/*
+ * Implementation of hook_migrate_api().
+ */
+function flag_migrate_api() {
+  $api = array(
+    'api' => 2,
+    'destination handlers' => array(
+      'MigrateNodeFlagHandler',
+      'MigrateUserFlagHandler',
+    ),
+  );
+  return $api;
+}
+
+/**
+ * Destination class implementing when you want just an insert into flagging table.
+ */
+class MigrateDestinationFlag extends MigrateDestination {
+
+  public function __construct($fid) {
+    parent::__construct();
+
+    $this->fid = $fid;
+  }
+
+  public function __toString() {
+    $flag = flag_get_flag(NULL, $this->fid);
+    return t('flag (!flag)', array('!flag' => $flag->name));
+  }
+
+  static public function getKeySchema() {
+
+    return array(
+      'flagging_id' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+      ),
+    );
+  }
+
+  /**
+   * Delete a membership.
+   *
+   * @param $id
+   *  IDs to be deleted.
+   */
+  public function bulkRollback(array$ids) {
+    migrate_instrument_start(__METHOD__);
+
+    db_delete('flagging')->condition('flagging_id', $ids, 'IN')->execute();
+
+    migrate_instrument_stop(__METHOD__);
+  }
+
+  /**
+   * Import a single flag_content.
+   *
+   * @param $entity
+   *  Object object to build. Prefilled with any fields mapped in the Migration.
+   * @param $row
+   *  Raw source data object - passed through to prepare/complete handlers.
+   *
+   * @return array
+   *  Array of key fields of the object that was saved if
+   *  successful. FALSE on failure.
+   */
+  public function import(stdClass$entity, stdClass$row) {
+
+
+    // Updating previously-migrated content?
+    if (isset($row->migrate_map_destid1)) {
+      if (isset($entity->flagging_id)) {
+        if ($entity->flagging_id != $row->migrate_map_destid1) {
+          throw new MigrateException(t("Incoming id !id and map destination id !destid don't match.",
+              array('!id' => $entity->flagging_id, '!destid' => $row->migrate_map_destid1)
+            ));
+        }
+      }
+      else {
+        $entity->flagging_id = $row->migrate_map_destid1;
+      }
+    }
+    // Otherwise, clear out the fcid, just to be safe.
+    else {
+      unset($entity->flagging_id);
+    }
+
+
+    if (isset($entity->timestamp)) {
+      $entity->timestamp = Migration::timestamp($entity->timestamp);
+    }
+
+    $entity->fid = $this->fid;
+
+    if (!empty($entity->flagging_id)) {
+      $return = drupal_write_record('flagging', $entity, array('flagging_id'));
+    }
+    else {
+      $return = drupal_write_record('flagging', $entity);
+    }
+    if ($return) {
+      // Increment the number of updated or inserted records by checking the
+      // result of drupal_write_record.
+      ($return == SAVED_NEW) ? $this->numCreated++ : $this->numUpdated++;
+
+      // Update the flag_counts table.
+      $count = db_select('flagging')->fields('flagging')->condition('fid', $this->fid)->condition('entity_type', $entity->entity_type)->condition('entity_id', $entity->entity_type)->countQuery()->execute()->fetchField();
+
+      db_merge('flag_counts')->key(array(
+          'fid' => $this->fid,
+          'entity_id' => $entity->entity_id,
+        ))->fields(array(
+          'entity_type' => $entity->entity_type,
+          'count' => $count,
+          'last_updated' => REQUEST_TIME,
+        ))->execute();
+
+      return array($entity->flagging_id);
+    }
+  }
+
+  public function fields() {
+    return array(
+      'flagging_id' => 'Flag content ID',
+      'fid' => 'Flag ID',
+      'entity_type' => '',
+      'entity_id' => '',
+      'uid' => 'User ID',
+      'timestamp' => '',
+    );
+  }
+}
+
+/**
+ * Field handler - this will expose flags as fields on the object they're
+ * attached to, and set the flag to the value mapped in addFieldMapping().
+ */
+abstract class MigrateFlagHandler extends MigrateDestinationHandler {
+
+  /**
+   * Make the flags assigned to this object visible.
+   */
+  public function fields($entity_type, $bundle) {
+    $fields = array();
+    if (module_exists('flag')) {
+      $flags = flag_get_flags($entity_type, $bundle);
+      foreach ($flags as $flag_name => $flag) {
+        $fields[$flag_name] = $flag->title;
+      }
+    }
+    return $fields;
+  }
+}
+
+/**
+ * Because we can't identify what kind of entity is passed to complete, we
+ * implement a separate handler for each type.
+ */
+class MigrateNodeFlagHandler extends MigrateFlagHandler {
+  public function __construct() {
+    $this->registerTypes(array('node'));
+  }
+
+  public function complete($node, stdClass$row) {
+    if (!module_exists('flag')) {
+      return;
+    }
+
+    $flags = flag_get_flags('node', $node->type);
+    foreach ($flags as $flag_name => $flag) {
+      if (!empty($node->$flag_name)) {
+        flag('flag', $flag_name, $node->nid);
+      }
+    }
+  }
+}
+
+class MigrateUserFlagHandler extends MigrateFlagHandler {
+  public function __construct() {
+    $this->registerTypes(array('user'));
+  }
+
+  public function complete($user, stdClass$row) {
+    if (!module_exists('flag')) {
+      return;
+    }
+
+    $flags = flag_get_flags('user', 'user');
+    foreach ($flags as $flag_name => $flag) {
+      if (!empty($user->$flag_name)) {
+        flag('flag', $flag_name, $user->uid);
+      }
+    }
+  }
+}
+
