Finalize sdk interface.
diff --git a/examples/demo-movielens/batch_import.py b/examples/demo-movielens/batch_import.py
index 14fbedb..fa2e1c0 100644
--- a/examples/demo-movielens/batch_import.py
+++ b/examples/demo-movielens/batch_import.py
@@ -17,7 +17,7 @@
         sys.stdout.write('\r[Info] %s' % count)
         sys.stdout.flush()
 
-    client.aset_user(v.uid)
+    client.aset_user(uid=v.uid)
 
   sys.stdout.write('\r[Info] %s users were imported.\n' % count)
   sys.stdout.flush()
@@ -34,8 +34,9 @@
         sys.stdout.flush()
 
     itypes = ("movie",) + v.genres
-    client.aset_item(v.iid,
-      { "pio_itypes" : list(itypes),
+    client.aset_item(iid=v.iid,
+      properties={ 
+        "pio_itypes" : list(itypes),
         "pio_starttime" : v.release_date.isoformat() + 'Z',
         "name" : v.name,
         "year" : v.year } )
@@ -55,16 +56,15 @@
         sys.stdout.flush()
 
     properties = { "pio_rating" : int(v.rating) }
-    req = client.acreate_event({
-      "event" : "rate",
-      "entityType" : "pio_user",
-      "entityId" : v.uid,
-      "targetEntityType" : "pio_item",
-      "targetEntityId": v.iid,
-      "properties" : properties,
-      "appId" : app_id,
-      "eventTime" : v.t.replace(tzinfo=pytz.utc).isoformat(),
-    })
+    req = client.acreate_event(
+        event="rate",
+        entity_type="pio_user",
+        entity_id=v.uid,
+        target_entity_type="pio_item",
+        target_entity_id=v.iid,
+        properties=properties,
+        event_time=v.t.replace(tzinfo=pytz.utc),
+        )
 
   sys.stdout.write('\r[Info] %s rate actions were imported.\n' % count)
   sys.stdout.flush()
diff --git a/examples/event_sample.py b/examples/event_sample.py
index 45e5afc..d076371 100644
--- a/examples/event_sample.py
+++ b/examples/event_sample.py
@@ -2,53 +2,50 @@
 from predictionio import NotFoundError
 from datetime import datetime
 import pytz
+import sys
 
-client = EventClient(app_id=6, url="http://localhost:7070")
+client = EventClient(app_id=4, url="http://localhost:7070")
 
 # Check status
 print("Check status")
 print(client.get_status())
 
 # First event
-first_event_data = {
-  "predictionKey": "my_prediction_key",
-  "appId": 4,
-  "event": "my_event",
-  "entityType": "user",
-  "entityId": "uid",
-  "properties": {
+first_event_properties = {
     "prop1" : 1,
     "prop2" : "value2",
     "prop3" : [1, 2, 3],
     "prop4" : True,
     "prop5" : ["a", "b", "c"],
     "prop6" : 4.56 ,
-  },
-}
-first_event_response = client.create_event(first_event_data)
+    }
+first_event_response = client.create_event(
+    event="my_event",
+    entity_type="user",
+    entity_id="uid",
+    properties=first_event_properties)
 print("First Event response")
 print(first_event_response)
 print
 
 # Second event
-second_event_data = {
-  "appId" : 4,
-  "predictionKey" : "my_prediction_key",
-  "event" : "my_event",
-  "entityType" : "user",
-  "entityId" : "uid",
-  "targetEntityType" : "item",
-  "targetEntityId" : "iid",
-  "properties" : {
+second_event_properties = {
     "someProperty" : "value1",
-    "anotherProperty" : "value2"
-  },
-  "eventTime" : "2004-12-13T21:39:45.618Z",
-}
+    "anotherProperty" : "value2",
+    }
+second_event_response = client.create_event(
+    event="my_event",
+    entity_type="user",
+    entity_id="uid",
+    target_entity_type="item",
+    target_entity_id="iid",
+    properties=second_event_properties,
+    event_time=datetime(2014, 12, 13, 21, 38, 45, 618, pytz.utc))
 print("Second Event response")
-print(client.create_event(second_event_data))
+print(second_event_response)
 print
 
+
 # Get the first event from Event Server
 first_event_id = first_event_response.json_body["eventId"]
 print("Get Event")
@@ -96,7 +93,6 @@
 
 # The SDK also support specifying the eventTime. It is useful for importing 
 # events happened in the past.
-#foo_time = datetime(2014, 8, 31, 4, 56, 1, 2, tzinfo=pytz.timezone('US/Pacific'))
 foo_time = datetime(2014, 8, 31, 4, 56, tzinfo=pytz.timezone('US/Pacific'))
 print("Create user at " + str(foo_time))
 print(client.set_user("Jarvis", {}, foo_time))
diff --git a/examples/import_yahoo.py b/examples/import_yahoo.py
index c7ac26f..69421d4 100644
--- a/examples/import_yahoo.py
+++ b/examples/import_yahoo.py
@@ -104,16 +104,13 @@
 
   properties = {'yahoo': yahoo_data}
 
-  data = {
-      'event': '$set',
-      'entityType': 'yahoo',
-      'entityId': ticker,
-      'properties': properties,
-      'appId': app_id,
-      'eventTime': event_time.replace(tzinfo=pytz.utc).isoformat(),
-      }
-
-  response = client.create_event(data)
+  response = client.create_event(
+      event='$set',
+      entity_type='yahoo',
+      entity_id=ticker,
+      properties=properties,
+      event_time=event_time.replace(tzinfo=pytz.utc))
+      
   print(response)
 
 
@@ -207,5 +204,5 @@
 
 if __name__ == '__main__':
   #import_all(app_id=2)
-  #import_data_with_gaps(app_id=1)
-  import_one(app_id=1)
+  import_data_with_gaps(app_id=1)
+  #import_one(app_id=1)
diff --git a/predictionio/__init__.py b/predictionio/__init__.py
index 5cc0f65..aa896da 100644
--- a/predictionio/__init__.py
+++ b/predictionio/__init__.py
@@ -41,8 +41,20 @@
   pass
 
 
-def now_if_none(t):
-  return datetime.now(pytz.utc) if t is None else t
+def event_time_validation(t):
+  """ Validate event_time according to EventAPI Specification.
+  """
+
+  if t is None:
+    return datetime.now(pytz.utc)
+
+  if type(t) != datetime:
+    raise AttributeError("event_time must be datetime.datetime")
+
+  if t.tzinfo is None:
+    raise AttributeError("event_time must have tzinfo")
+
+  return t
 
 
 class BaseClient(object):
@@ -146,15 +158,40 @@
     super(EventClient, self).__init__(url, threads, qsize, timeout)
     self.app_id = app_id
 
-  def acreate_event(self, data):
+  def acreate_event(self, event, entity_type, entity_id,
+      target_entity_type=None, target_entity_id=None, properties=None,
+      event_time=None):
+    data = {
+        "appId": self.app_id,
+        "event": event,
+        "entityType": entity_type,
+        "entityId": entity_id,
+        }
+
+    if target_entity_type is not None:
+      data["targetEntityType"] = target_entity_type
+
+    if target_entity_id is not None:
+      data["targetEntityId"] = target_entity_id
+
+    if properties is not None:
+      data["properties"] = properties
+
+    event_time = event_time_validation(event_time)
+    data["eventTime"] = event_time.isoformat()
+    
     path = "/events.json"
     request = AsyncRequest("POST", path, **data)
     request.set_rfunc(self._acreate_resp)
     self._connection.make_request(request)
     return request
 
-  def create_event(self, data):
-    return self.acreate_event(data).get_response()
+  def create_event(self, event, entity_type, entity_id,
+      target_entity_type=None, target_entity_id=None, properties=None,
+      event_time=None):
+    return self.acreate_event(event, entity_type, entity_id,
+        target_entity_type, target_entity_id, properties, 
+        event_time).get_response()
 
   def aget_event(self, event_id):
     enc_event_id = urllib.quote(event_id, "") # replace special char with %xx
@@ -181,107 +218,86 @@
   ## Below are helper functions
 
   def aset_user(self, uid, properties={}, event_time=None):
-    event_time = now_if_none(event_time)
-
     """set properties of an user"""
-    return self.acreate_event({
-      "event" : "$set",
-      "entityType" : "pio_user",
-      "entityId" : uid,
-      "properties" : properties,
-      "appId" : self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+      event="$set",
+      entity_type="pio_user",
+      entity_id=uid,
+      properties=properties,
+      event_time=event_time,
+    )
 
   def set_user(self, uid, properties={}, event_time=None):
     return self.aset_user(uid, properties, event_time).get_response()
 
   def aunset_user(self, uid, properties, event_time=None):
     """unset properties of an user"""
-    event_time = now_if_none(event_time)
-
     # check properties={}, it cannot be empty
-    return self.acreate_event({
-      "event" : "$unset",
-      "entityType" : "pio_user",
-      "entityId" : uid,
-      "properties" : properties,
-      "appId" : self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event="$unset",
+        entity_type="pio_user",
+        entity_id=uid,
+        properties=properties,
+        event_time=event_time,
+        )
 
   def unset_user(self, uid, properties, event_time=None):
     return self.aunset_user(uid, properties, event_time).get_response()
 
   def adelete_user(self, uid, event_time=None):
     """set properties of an user"""
-    event_time = now_if_none(event_time)
-    return self.acreate_event({
-      "event" : "$delete",
-      "entityType" : "pio_user",
-      "entityId" : uid,
-      "appId": self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event="$delete",
+        entity_type="pio_user",
+        entity_id=uid,
+        event_time=event_time)
 
   def delete_user(self, uid, event_time=None):
     return self.adelete_user(uid, event_time).get_response()
 
   def aset_item(self, iid, properties={}, event_time=None):
-    event_time = now_if_none(event_time)
-    return self.acreate_event({
-      "event" : "$set",
-      "entityType" : "pio_item",
-      "entityId" : iid,
-      "properties" : properties,
-      "appId" : self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event="$set",
+        entity_type="pio_item",
+        entity_id=iid,
+        properties=properties,
+        event_time=event_time)
 
   def set_item(self, iid, properties={}, event_time=None):
-    return self.aset_item(iid, properties).get_response()
+    return self.aset_item(iid, properties, event_time).get_response()
 
   def aunset_item(self, iid, properties={}, event_time=None):
-    event_time = now_if_none(event_time)
-    return self.acreate_event({
-      "event" : "$unset",
-      "entityType" : "pio_item",
-      "entityId" : iid,
-      "properties" : properties,
-      "appId" : self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event="$unset",
+        entity_type="pio_item",
+        entity_id=iid,
+        properties=properties,
+        event_time=event_time)
 
   def unset_item(self, iid, properties={}, event_time=None):
     return self.aunset_item(iid, properties, event_time).get_response()
 
   def adelete_item(self, iid, event_time=None):
     """set properties of an user"""
-    event_time = now_if_none(event_time)
-    return self.acreate_event({
-      "event" : "$delete",
-      "entityType" : "pio_item",
-      "entityId" : iid,
-      "appId": self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event="$delete",
+        entity_type="pio_item",
+        entity_id=iid,
+        event_time=event_time)
 
   def delete_item(self, iid, event_time=None):
     return self.adelete_item(iid, event_time).get_response()
 
   def arecord_user_action_on_item(self, action, uid, iid, properties={},
       event_time=None):
-    event_time = now_if_none(event_time)
-    return self.acreate_event({
-      "event" : action,
-      "entityType" : "pio_user",
-      "entityId" : uid,
-      "targetEntityType" : "pio_item",
-      "targetEntityId": iid,
-      "properties" : properties,
-      "appId" : self.app_id,
-      "eventTime": event_time.isoformat(),
-    })
+    return self.acreate_event(
+        event=action,
+        entity_type="pio_user",
+        entity_id=uid,
+        target_entity_type="pio_item",
+        target_entity_id=iid,
+        properties=properties,
+        event_time=event_time)
 
   def record_user_action_on_item(self, action, uid, iid, properties={},
       event_time=None):