diff --git a/src/main/java/org/gitlab4j/api/systemhooks/GroupMemberSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/GroupMemberSystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..da6dcc38f408e8a18ceea73e1a4888d66f4feac8
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/GroupMemberSystemHookEvent.java
@@ -0,0 +1,115 @@
+package org.gitlab4j.api.systemhooks;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class GroupMemberSystemHookEvent implements SystemHookEvent {
+    
+    public static final String NEW_GROUP_MEMBER_EVENT = "user_add_to_group";
+    public static final String GROUP_MEMBER_REMOVED_EVENT = "user_remove_from_group";
+    
+    private Date createdAt;
+    private Date updatedAt;
+    private String eventName;
+    private String groupAccess;
+    private String groupName;
+    private String groupPath;
+    private Integer groupId;
+    private String userEmail;
+    private String userName;
+    private String userUsername;
+    private Integer userId;
+
+    public Date getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Date createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Date getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Date updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getEventName() {
+        return this.eventName;
+    }
+
+    public void setEventName(String eventName) {
+        this.eventName = eventName;
+    }
+
+    public String getGroupAccess() {
+        return groupAccess;
+    }
+
+    public void setGroupAccess(String groupAccess) {
+        this.groupAccess = groupAccess;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String groupName) {
+        this.groupName = groupName;
+    }
+
+    public String getGroupPath() {
+        return groupPath;
+    }
+
+    public void setGroupPath(String groupPath) {
+        this.groupPath = groupPath;
+    }
+
+    public Integer getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(Integer groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getUserEmail() {
+        return userEmail;
+    }
+
+    public void setUserEmail(String userEmail) {
+        this.userEmail = userEmail;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getUserUsername() {
+        return userUsername;
+    }
+
+    public void setUserUsername(String userUsername) {
+        this.userUsername = userUsername;
+    }
+
+    public Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/GroupSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/GroupSystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..546178f65b2469ec2330c8fed35db4eccb931c4a
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/GroupSystemHookEvent.java
@@ -0,0 +1,117 @@
+package org.gitlab4j.api.systemhooks;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class GroupSystemHookEvent implements SystemHookEvent {
+    
+    public static final String GROUP_CREATE_EVENT = "group_create";
+    public static final String GROUP_DESTROY_EVENT = "group_destroy";
+    public static final String GROUP_RENAME_EVENT = "group_rename";
+    
+    private Date createdAt;
+    private Date updatedAt;
+    private String eventName;
+    private String name;
+    private String path;
+    private String fullPath;
+    private Integer groupId;
+    private String ownerEmail;
+    private String ownerName;
+    private String oldPath;
+    private String oldFullPath;
+
+
+    public Date getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Date createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Date getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Date updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getEventName() {
+        return this.eventName;
+    }
+
+    public void setEventName(String eventName) {
+        this.eventName = eventName;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getFullPath() {
+        return fullPath;
+    }
+
+    public void setFullPath(String fullPath) {
+        this.fullPath = fullPath;
+    }
+
+    public Integer getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(Integer groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getOwnerEmail() {
+        return ownerEmail;
+    }
+
+    public void setOwnerEmail(String ownerEmail) {
+        this.ownerEmail = ownerEmail;
+    }
+
+    public String getOwnerName() {
+        return ownerName;
+    }
+
+    public void setOwnerName(String ownerName) {
+        this.ownerName = ownerName;
+    }
+
+    public String getOldPath() {
+        return oldPath;
+    }
+
+    public void setOldPath(String oldPath) {
+        this.oldPath = oldPath;
+    }
+
+    public String getOldFullPath() {
+        return oldFullPath;
+    }
+
+    public void setOldFullPath(String oldFullPath) {
+        this.oldFullPath = oldFullPath;
+    }
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/KeySystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/KeySystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..91cb019f1dc21ec33cbdb84e4ec4124e109dd8e4
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/KeySystemHookEvent.java
@@ -0,0 +1,70 @@
+package org.gitlab4j.api.systemhooks;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class KeySystemHookEvent implements SystemHookEvent {
+    
+    public static final String KEY_CREATE_EVENT = "key_create";
+    public static final String KEY_DESTROY_EVENT = "key_destroy";
+    
+    private Date createdAt;
+    private Date updatedAt;
+    private String eventName;
+    private String username;
+    private String key;
+    private Integer id;
+
+    public Date getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Date createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Date getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Date updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getEventName() {
+        return this.eventName;
+    }
+
+    public void setEventName(String eventName) {
+        this.eventName = eventName;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/PushSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/PushSystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d1221c5fc12bf852acc5fefd2bf3517d3796517
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/PushSystemHookEvent.java
@@ -0,0 +1,13 @@
+package org.gitlab4j.api.systemhooks;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gitlab4j.api.webhook.AbstractPushEvent;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PushSystemHookEvent extends AbstractPushEvent implements SystemHookEvent {
+    public static final String PUSH_EVENT = "push";
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/RepositoryChange.java b/src/main/java/org/gitlab4j/api/systemhooks/RepositoryChange.java
new file mode 100644
index 0000000000000000000000000000000000000000..513ecd58f64b53f1ea8b201b3ac58025824dc187
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/RepositoryChange.java
@@ -0,0 +1,38 @@
+package org.gitlab4j.api.systemhooks;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RepositoryChange {
+
+    private String after;
+    private String before;
+    private String ref;
+
+    public String getAfter() {
+        return this.after;
+    }
+
+    public void setAfter(String after) {
+        this.after = after;
+    }
+
+    public String getBefore() {
+        return this.before;
+    }
+
+    public void setBefore(String before) {
+        this.before = before;
+    }
+
+    public String getRef() {
+        return this.ref;
+    }
+
+    public void setRef(String ref) {
+        this.ref = ref;
+    }
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/RepositorySystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/RepositorySystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..bef380a10d7c56a0c61a25b95223463298b5949b
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/RepositorySystemHookEvent.java
@@ -0,0 +1,101 @@
+package org.gitlab4j.api.systemhooks;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gitlab4j.api.webhook.EventProject;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RepositorySystemHookEvent implements SystemHookEvent {
+
+    public static final String REPOSITORY_UPDATE_EVENT = "repository_update";
+
+    private String eventName;
+    private Integer userId;
+    private String userName;
+    private String userEmail;
+    private String userAvatar;
+
+    private Integer projectId;
+    private EventProject project;
+
+    private List<RepositoryChange> changes;
+    private List<String> refs;
+
+
+    public String getEventName() {
+        return (eventName);
+    }
+
+    public void setEventName(String eventName) {
+        this.eventName = eventName;
+    }
+
+    public Integer getUserId() {
+        return this.userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return this.userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getUserEmail() {
+        return userEmail;
+    }
+
+    public void setUserEmail(String userEmail) {
+        this.userEmail = userEmail;
+    }
+
+    public String getUserAvatar() {
+        return userAvatar;
+    }
+
+    public void setUserAvatar(String userAvatar) {
+        this.userAvatar = userAvatar;
+    }
+
+    public Integer getProjectId() {
+        return this.projectId;
+    }
+
+    public void setProjectId(Integer projectId) {
+        this.projectId = projectId;
+    }
+
+    public EventProject getProject() {
+        return project;
+    }
+
+    public void setProject(EventProject project) {
+        this.project = project;
+    }
+
+    public List<RepositoryChange> getChanges() {
+        return changes;
+    }
+
+    public void setChanges(List<RepositoryChange> changes) {
+        this.changes = changes;
+    }
+
+    public List<String> getRefs() {
+        return refs;
+    }
+
+    public void setRefs(List<String> refs) {
+        this.refs = refs;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookEvent.java
index c17454d88deee49f02fa7ab574e652a65bfb67fa..3dc845886406fc58c2f7602340a4a26b1b0139c2 100644
--- a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookEvent.java
+++ b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookEvent.java
@@ -4,17 +4,54 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
 @JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
-    include=JsonTypeInfo.As.PROPERTY,
     property="event_name")
 @JsonSubTypes({
-    @JsonSubTypes.Type(value = ProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_CREATE_EVENT),
-    @JsonSubTypes.Type(value = ProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_DESTROY_EVENT),
-    @JsonSubTypes.Type(value = ProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_RENAME_EVENT),
-    @JsonSubTypes.Type(value = ProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_TRANSFER_EVENT),
-    @JsonSubTypes.Type(value = ProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_UPDATE_EVENT),
-    @JsonSubTypes.Type(value = TeamMemberSystemHookEvent.class, name = TeamMemberSystemHookEvent.NEW_TEAM_MEMBER_EVENT),
-    @JsonSubTypes.Type(value = TeamMemberSystemHookEvent.class, name = TeamMemberSystemHookEvent.TEAM_MEMBER_REMOVED_EVENT)
+    @JsonSubTypes.Type(value = CreateProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_CREATE_EVENT),
+    @JsonSubTypes.Type(value = DestroyProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_DESTROY_EVENT),
+    @JsonSubTypes.Type(value = RenameProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_RENAME_EVENT),
+    @JsonSubTypes.Type(value = TransferProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_TRANSFER_EVENT),
+    @JsonSubTypes.Type(value = UpdateProjectSystemHookEvent.class, name = ProjectSystemHookEvent.PROJECT_UPDATE_EVENT),
+    @JsonSubTypes.Type(value = NewTeamMemberSystemHookEvent.class, name = TeamMemberSystemHookEvent.NEW_TEAM_MEMBER_EVENT),
+    @JsonSubTypes.Type(value = RemoveTeamMemberSystemHookEvent.class, name = TeamMemberSystemHookEvent.TEAM_MEMBER_REMOVED_EVENT),
+    @JsonSubTypes.Type(value = CreateUserSystemHookEvent.class, name = UserSystemHookEvent.USER_CREATE_EVENT),
+    @JsonSubTypes.Type(value = DestroyUserSystemHookEvent.class, name = UserSystemHookEvent.USER_DESTROY_EVENT),
+    @JsonSubTypes.Type(value = RenameUserSystemHookEvent.class, name = UserSystemHookEvent.USER_RENAME_EVENT),
+    @JsonSubTypes.Type(value = CreateKeySystemHookEvent.class, name = KeySystemHookEvent.KEY_CREATE_EVENT),
+    @JsonSubTypes.Type(value = DestroyKeySystemHookEvent.class, name = KeySystemHookEvent.KEY_DESTROY_EVENT),
+    @JsonSubTypes.Type(value = CreateGroupSystemHookEvent.class, name = GroupSystemHookEvent.GROUP_CREATE_EVENT),
+    @JsonSubTypes.Type(value = DestroyGroupSystemHookEvent.class, name = GroupSystemHookEvent.GROUP_DESTROY_EVENT),
+    @JsonSubTypes.Type(value = RenameGroupSystemHookEvent.class, name = GroupSystemHookEvent.GROUP_RENAME_EVENT),
+    @JsonSubTypes.Type(value = NewGroupMemberSystemHookEvent.class, name = GroupMemberSystemHookEvent.NEW_GROUP_MEMBER_EVENT),
+    @JsonSubTypes.Type(value = RemoveGroupMemberSystemHookEvent.class, name = GroupMemberSystemHookEvent.GROUP_MEMBER_REMOVED_EVENT),
+    @JsonSubTypes.Type(value = PushSystemHookEvent.class, name = PushSystemHookEvent.PUSH_EVENT),
+    @JsonSubTypes.Type(value = TagPushSystemHookEvent.class, name = TagPushSystemHookEvent.TAG_PUSH_EVENT),
+    @JsonSubTypes.Type(value = RepositorySystemHookEvent.class, name = RepositorySystemHookEvent.REPOSITORY_UPDATE_EVENT)
 })
 public interface SystemHookEvent {
     public String getEventName();
 }
+
+// All of the following class definitions are needed to make the above work.
+// Jackson has a tough time mapping the same class to multiple IDs
+class CreateProjectSystemHookEvent extends ProjectSystemHookEvent {}
+class DestroyProjectSystemHookEvent extends ProjectSystemHookEvent {}
+class RenameProjectSystemHookEvent extends ProjectSystemHookEvent {}
+class TransferProjectSystemHookEvent extends ProjectSystemHookEvent {}
+class UpdateProjectSystemHookEvent extends ProjectSystemHookEvent {}
+
+class NewTeamMemberSystemHookEvent extends TeamMemberSystemHookEvent {}
+class RemoveTeamMemberSystemHookEvent extends TeamMemberSystemHookEvent {}
+
+class CreateUserSystemHookEvent extends UserSystemHookEvent {}
+class DestroyUserSystemHookEvent extends UserSystemHookEvent {}
+class RenameUserSystemHookEvent extends UserSystemHookEvent {}
+
+class CreateKeySystemHookEvent extends KeySystemHookEvent {}
+class DestroyKeySystemHookEvent extends KeySystemHookEvent {}
+
+class CreateGroupSystemHookEvent extends GroupSystemHookEvent {}
+class DestroyGroupSystemHookEvent extends GroupSystemHookEvent {}
+class RenameGroupSystemHookEvent extends GroupSystemHookEvent {}
+
+class NewGroupMemberSystemHookEvent extends GroupMemberSystemHookEvent {}
+class RemoveGroupMemberSystemHookEvent extends GroupMemberSystemHookEvent {}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookListener.java b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookListener.java
index 5c9a0181cf2580a475a5250b4fc0f1639d0fb204..c496f018dd26e302116ec0f909bfce0ca3a14760 100644
--- a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookListener.java
+++ b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookListener.java
@@ -20,4 +20,53 @@ public interface SystemHookListener extends java.util.EventListener {
      * @param event the TeamMemberSystemHookEvent instance containing info on the team member event
      */
     public void onTeamMemberEvent(TeamMemberSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook user event has been received.
+     *
+     * @param event the UserSystemHookEvent instance containing info on the user event
+     */
+    public void onUserEvent(UserSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook key event has been received.
+     *
+     * @param event the KeySystemHookEvent instance containing info on the key event
+     */
+    public void onKeyEvent(KeySystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook group event has been received.
+     *
+     * @param event the GroupSystemHookEvent instance containing info on the key event
+     */
+    public void onGroupEvent(GroupSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook group member event has been received.
+     *
+     * @param event the GroupMemberSystemHookEvent instance containing info on the key event
+     */
+    public void onGroupMemberEvent(GroupMemberSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook push event has been received.
+     *
+     * @param event the PushSystemHookEvent instance containing info on the key event
+     */
+    public void onPushEvent(PushSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook tag push event has been received.
+     *
+     * @param event the TagPushSystemHookEvent instance containing info on the key event
+     */
+    public void onTagPushEvent(TagPushSystemHookEvent event);
+
+    /**
+     * This method is called when a System Hook repository event has been received.
+     *
+     * @param event the RepositorySystemHookEvent instance containing info on the key event
+     */
+    public void onRepositoryEvent(RepositorySystemHookEvent event);
 }
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookManager.java b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookManager.java
index fde49c1081687e0f4ed8f66631f3254243ad6931..5a6f3e31a4a65cb6f78b431a1e48bc0de70e0c07 100644
--- a/src/main/java/org/gitlab4j/api/systemhooks/SystemHookManager.java
+++ b/src/main/java/org/gitlab4j/api/systemhooks/SystemHookManager.java
@@ -113,9 +113,12 @@ public class SystemHookManager extends HookManager {
      * @throws GitLabApiException if the event is not supported
      */
     public void handleEvent(SystemHookEvent event) throws GitLabApiException {
-
-        LOG.info("handleEvent: object_kind=" + event.getEventName());
-        fireEvent(event);
+        if (event != null) {
+            LOG.info("handleEvent:" + event.getClass().getSimpleName() + ", eventName=" + event.getEventName());
+            fireEvent(event);
+        } else {
+            LOG.warning("handleEvent: provided event cannot be null!");
+        }
     }
 
     /**
@@ -151,6 +154,20 @@ public class SystemHookManager extends HookManager {
             fireProjectEvent((ProjectSystemHookEvent) event);
         } else if (event instanceof TeamMemberSystemHookEvent) {
             fireTeamMemberEvent((TeamMemberSystemHookEvent) event);
+        } else if (event instanceof UserSystemHookEvent) {
+            fireUserEvent((UserSystemHookEvent) event);
+        } else if (event instanceof KeySystemHookEvent) {
+            fireKeyEvent((KeySystemHookEvent) event);
+        } else if (event instanceof GroupSystemHookEvent) {
+            fireGroupEvent((GroupSystemHookEvent) event);
+        } else if (event instanceof GroupMemberSystemHookEvent) {
+            fireGroupMemberEvent((GroupMemberSystemHookEvent) event);
+        } else if (event instanceof PushSystemHookEvent) {
+            firePushEvent((PushSystemHookEvent) event);
+        } else if (event instanceof TagPushSystemHookEvent) {
+            fireTagPushEvent((TagPushSystemHookEvent) event);
+        } else if (event instanceof RepositorySystemHookEvent) {
+            fireRepositoryEvent((RepositorySystemHookEvent) event);
         } else {
             String message = "Unsupported event, event_named=" + event.getEventName();
             LOG.warning(message);
@@ -159,16 +176,56 @@ public class SystemHookManager extends HookManager {
     }
 
     protected void fireProjectEvent(ProjectSystemHookEvent event) {
-
         for (SystemHookListener listener : systemHookListeners) {
             listener.onProjectEvent(event);
         }
     }
 
     protected void fireTeamMemberEvent(TeamMemberSystemHookEvent event) {
-
         for (SystemHookListener listener : systemHookListeners) {
             listener.onTeamMemberEvent(event);
         }
     }
+
+    protected void fireUserEvent(UserSystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onUserEvent(event);
+        }
+    }
+
+    protected void fireKeyEvent(KeySystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onKeyEvent(event);
+        }
+    }
+
+    protected void fireGroupEvent(GroupSystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onGroupEvent(event);
+        }
+    }
+
+    protected void fireGroupMemberEvent(GroupMemberSystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onGroupMemberEvent(event);
+        }
+    }
+
+    protected void firePushEvent(PushSystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onPushEvent(event);
+        }
+    }
+
+    protected void fireTagPushEvent(TagPushSystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onTagPushEvent(event);
+        }
+    }
+
+    protected void fireRepositoryEvent(RepositorySystemHookEvent event) {
+        for (SystemHookListener listener : systemHookListeners) {
+            listener.onRepositoryEvent(event);
+        }
+    }
 }
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/TagPushSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/TagPushSystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc628fd696aed473d872ccde57b6d74cf288a7f3
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/TagPushSystemHookEvent.java
@@ -0,0 +1,13 @@
+package org.gitlab4j.api.systemhooks;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gitlab4j.api.webhook.AbstractPushEvent;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class TagPushSystemHookEvent extends AbstractPushEvent implements SystemHookEvent {
+    public static final String TAG_PUSH_EVENT = "tag_push";
+}
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/TeamMemberSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/TeamMemberSystemHookEvent.java
index b9602c33b705498524b94ef46e90a0836511ba9e..b75c04d1bfe1f95990f36a4be0e5e051bd6de745 100644
--- a/src/main/java/org/gitlab4j/api/systemhooks/TeamMemberSystemHookEvent.java
+++ b/src/main/java/org/gitlab4j/api/systemhooks/TeamMemberSystemHookEvent.java
@@ -132,12 +132,4 @@ public class TeamMemberSystemHookEvent implements SystemHookEvent {
     public void setProjectVisibility(Visibility projectVisibility) {
         this.projectVisibility = projectVisibility;
     }
-
-    public static String getNewTeamMemberEvent() {
-        return NEW_TEAM_MEMBER_EVENT;
-    }
-
-    public static String getTeamMemberRemovedEvent() {
-        return TEAM_MEMBER_REMOVED_EVENT;
-    }
 }
diff --git a/src/main/java/org/gitlab4j/api/systemhooks/UserSystemHookEvent.java b/src/main/java/org/gitlab4j/api/systemhooks/UserSystemHookEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc6c5689eb3ae411d09c0102315295de928494c7
--- /dev/null
+++ b/src/main/java/org/gitlab4j/api/systemhooks/UserSystemHookEvent.java
@@ -0,0 +1,89 @@
+package org.gitlab4j.api.systemhooks;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class UserSystemHookEvent implements SystemHookEvent {
+    
+    public static final String USER_CREATE_EVENT = "user_create";
+    public static final String USER_DESTROY_EVENT = "user_destroy";
+    public static final String USER_RENAME_EVENT = "user_rename";
+
+    private String eventName;
+    private Date createdAt;
+    private Date updatedAt;
+    private String email;
+    private String name;
+    private String username;
+    private Integer userId;
+    private String oldUsername;
+
+    public String getEventName() {
+        return this.eventName;
+    }
+
+    public void setEventName(String eventName) {
+        this.eventName = eventName;
+    }
+
+    public Date getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Date createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Date getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Date updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+
+    public String getOldUsername() {
+        return oldUsername;
+    }
+
+    public void setOldUsername(String oldUsername) {
+        this.oldUsername = oldUsername;
+    }
+}
diff --git a/src/main/java/org/gitlab4j/api/webhook/AbstractPushEvent.java b/src/main/java/org/gitlab4j/api/webhook/AbstractPushEvent.java
index f9445fc1752fc96299b40f65db0e871236f5be26..e4e09209a9ebdd0b7eed8aba59805f82691f7de2 100644
--- a/src/main/java/org/gitlab4j/api/webhook/AbstractPushEvent.java
+++ b/src/main/java/org/gitlab4j/api/webhook/AbstractPushEvent.java
@@ -8,7 +8,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
 @XmlAccessorType(XmlAccessType.FIELD)
-public abstract class AbstractPushEvent implements Event {
+public abstract class AbstractPushEvent {
 
     private String eventName;
 
@@ -28,10 +28,6 @@ public abstract class AbstractPushEvent implements Event {
     private List<EventCommit> commits;
     private Integer totalCommitsCount;
 
-    public abstract String getObjectKind();
-
-    public abstract void setObjectKind(String objectKind);
-
     public String getEventName() {
         return (eventName);
     }
diff --git a/src/main/java/org/gitlab4j/api/webhook/PushEvent.java b/src/main/java/org/gitlab4j/api/webhook/PushEvent.java
index 035c85edcb5681387a20e32b81350fafdbbc3beb..cc3725bebbf69e03c21d9b62c43478be10f855cf 100644
--- a/src/main/java/org/gitlab4j/api/webhook/PushEvent.java
+++ b/src/main/java/org/gitlab4j/api/webhook/PushEvent.java
@@ -5,11 +5,12 @@ import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 
 @XmlAccessorType(XmlAccessType.FIELD)
-public class PushEvent extends AbstractPushEvent {
+public class PushEvent extends AbstractPushEvent implements Event {
 
     public static final String X_GITLAB_EVENT = "Push Hook";
     public static final String OBJECT_KIND = "push";
 
+    @Override
     public String getObjectKind() {
         return (OBJECT_KIND);
     }
diff --git a/src/main/java/org/gitlab4j/api/webhook/TagPushEvent.java b/src/main/java/org/gitlab4j/api/webhook/TagPushEvent.java
index a3c680d50fa8acc10cce8b7762f46c2a54ad0dd2..4a93dd71169d8a85a0b517165c4c3cc0032e8284 100644
--- a/src/main/java/org/gitlab4j/api/webhook/TagPushEvent.java
+++ b/src/main/java/org/gitlab4j/api/webhook/TagPushEvent.java
@@ -5,11 +5,12 @@ import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 
 @XmlAccessorType(XmlAccessType.FIELD)
-public class TagPushEvent extends AbstractPushEvent {
+public class TagPushEvent extends AbstractPushEvent implements Event {
 
     public static final String X_GITLAB_EVENT = "Tag Push Hook";
     public static final String OBJECT_KIND = "tag_push";
 
+    @Override
     public String getObjectKind() {
         return (OBJECT_KIND);
     }
diff --git a/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java b/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java
index 0cdef31d7b061e9cac04755517298984b51b9280..e9574f657d37ed4de5c541d5c29c1dafbbfa56b8 100644
--- a/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java
+++ b/src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java
@@ -29,7 +29,6 @@ import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.List;
 
-import org.gitlab4j.api.GitLabApi;
 import org.gitlab4j.api.models.ArtifactsFile;
 import org.gitlab4j.api.models.Branch;
 import org.gitlab4j.api.models.Comment;
@@ -62,6 +61,8 @@ import org.gitlab4j.api.models.Tag;
 import org.gitlab4j.api.models.TreeItem;
 import org.gitlab4j.api.models.User;
 import org.gitlab4j.api.systemhooks.ProjectSystemHookEvent;
+import org.gitlab4j.api.systemhooks.PushSystemHookEvent;
+import org.gitlab4j.api.systemhooks.SystemHookEvent;
 import org.gitlab4j.api.systemhooks.TeamMemberSystemHookEvent;
 import org.gitlab4j.api.utils.JacksonJson;
 import org.junit.BeforeClass;
@@ -466,6 +467,72 @@ public class TestGitLabApiBeans {
         }
     }
 
+    @Test
+    public void testPushSystemHookEvent() {
+
+        try {
+            PushSystemHookEvent event = makeFakeApiCall(PushSystemHookEvent.class, "push-system-hook-event");
+            assertTrue(compareJson(event, "push-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testUserSystemHookEvent() {
+
+        try {
+            SystemHookEvent event = makeFakeApiCall(SystemHookEvent.class, "user-system-hook-event");
+            assertTrue(compareJson(event, "user-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGroupSystemHookEvent() {
+
+        try {
+            SystemHookEvent event = makeFakeApiCall(SystemHookEvent.class, "group-system-hook-event");
+            assertTrue(compareJson(event, "group-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGroupMemberSystemHookEvent() {
+
+        try {
+            SystemHookEvent event = makeFakeApiCall(SystemHookEvent.class, "group-member-system-hook-event");
+            assertTrue(compareJson(event, "group-member-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testTagPushSystemHookEvent() {
+
+        try {
+            SystemHookEvent event = makeFakeApiCall(SystemHookEvent.class, "tag-push-system-hook-event");
+            assertTrue(compareJson(event, "tag-push-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testRepositorySystemHookEvent() {
+
+        try {
+            SystemHookEvent event = makeFakeApiCall(SystemHookEvent.class, "repository-system-hook-event");
+            assertTrue(compareJson(event, "repository-system-hook-event"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
     @Test
     public void testLabels() {
 
diff --git a/src/test/resources/org/gitlab4j/api/group-member-system-hook-event.json b/src/test/resources/org/gitlab4j/api/group-member-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..f11a63a15888c6d5a4a15426eb21bf39be3fdc1c
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/group-member-system-hook-event.json
@@ -0,0 +1,13 @@
+{
+    "created_at": "2012-07-21T07:30:56Z",
+    "updated_at": "2012-07-21T07:38:22Z",
+    "event_name": "user_add_to_group",
+  "group_access": "Master",
+      "group_id": 78,
+    "group_name": "StoreCloud",
+    "group_path": "storecloud",
+    "user_email": "johnsmith@gmail.com",
+     "user_name": "John Smith",
+ "user_username": "johnsmith",
+       "user_id": 41
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/group-system-hook-event.json b/src/test/resources/org/gitlab4j/api/group-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..1f33f0f8598cc480ebcd2fdc959fa2ab5842462f
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/group-system-hook-event.json
@@ -0,0 +1,11 @@
+{
+     "event_name": "group_rename",
+     "created_at": "2017-10-30T15:09:00Z",
+     "updated_at": "2017-11-01T10:23:52Z",
+           "name": "Better Name",
+           "path": "better-name",
+      "full_path": "parent-group/better-name",
+       "group_id": 64,
+       "old_path": "old-name",
+  "old_full_path": "parent-group/old-name"
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/key-system-hook-event.json b/src/test/resources/org/gitlab4j/api/key-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..998f454caf842ed15b521187426ec4c7999e0353
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/key-system-hook-event.json
@@ -0,0 +1,8 @@
+{
+    "event_name": "key_destroy",
+    "created_at": "2014-08-18 18:45:16Z",
+    "updated_at": "2012-07-21T07:38:22Z",
+      "username": "root",
+           "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC58FwqHUbebw2SdT7SP4FxZ0w+lAO/erhy2ylhlcW/tZ3GY3mBu9VeeiSGoGz8hCx80Zrz+aQv28xfFfKlC8XQFpCWwsnWnQqO2Lv9bS8V1fIHgMxOHIt5Vs+9CAWGCCvUOAurjsUDoE2ALIXLDMKnJxcxD13XjWdK54j6ZXDB4syLF0C2PnAQSVY9X7MfCYwtuFmhQhKaBussAXpaVMRHltie3UYSBUUuZaB3J4cg/7TxlmxcNd+ppPRIpSZAB0NI6aOnqoBCpimscO/VpQRJMVLr3XiSYeT6HBiDXWHnIVPfQc03OGcaFqOit6p8lYKMaP/iUQLm+pgpZqrXZ9vB john@localhost",
+            "id": 4
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/push-system-hook-event.json b/src/test/resources/org/gitlab4j/api/push-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..9c17c8d774cd0eb7175ceb03465f693cb000b4ef
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/push-system-hook-event.json
@@ -0,0 +1,49 @@
+{
+  "event_name": "push",
+  "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
+  "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+  "ref": "refs/heads/master",
+  "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+  "user_id": 4,
+  "user_name": "John Smith",
+  "user_email": "john@example.com",
+  "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+  "project_id": 15,
+  "project":{
+    "name":"Diaspora",
+    "description":"",
+    "web_url":"http://example.com/mike/diaspora",
+    "git_ssh_url":"git@example.com:mike/diaspora.git",
+    "git_http_url":"http://example.com/mike/diaspora.git",
+    "namespace":"Mike",
+    "visibility_level":0,
+    "path_with_namespace":"mike/diaspora",
+    "default_branch":"master",
+    "homepage":"http://example.com/mike/diaspora",
+    "url":"git@example.com:mike/diaspora.git",
+    "ssh_url":"git@example.com:mike/diaspora.git",
+    "http_url":"http://example.com/mike/diaspora.git"
+  },
+  "repository":{
+    "name": "Diaspora",
+    "url": "git@example.com:mike/diaspora.git",
+    "description": "",
+    "homepage": "http://example.com/mike/diaspora",
+    "git_http_url":"http://example.com/mike/diaspora.git",
+    "git_ssh_url":"git@example.com:mike/diaspora.git",
+    "visibility_level":0
+  },
+  "commits": [
+    {
+      "id": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+      "message": "Add simple search to projects in public area",
+      "timestamp": "2013-05-13T18:18:08Z",
+      "url": "https://dev.gitlab.org/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+      "author": {
+        "name": "Dmitriy Zaporozhets",
+        "email": "dmitriy.zaporozhets@gmail.com"
+      }
+    }
+  ],
+  "total_commits_count": 1
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/repository-system-hook-event.json b/src/test/resources/org/gitlab4j/api/repository-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..d752bf9079f6b86a5b65db1fc4d7a5fb230550ac
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/repository-system-hook-event.json
@@ -0,0 +1,31 @@
+{
+  "event_name": "repository_update",
+  "user_id": 1,
+  "user_name": "John Smith",
+  "user_email": "admin@example.com",
+  "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+  "project_id": 1,
+  "project": {
+    "name":"Example",
+    "description":"",
+    "web_url":"http://example.com/jsmith/example",
+    "git_ssh_url":"git@example.com:jsmith/example.git",
+    "git_http_url":"http://example.com/jsmith/example.git",
+    "namespace":"Jsmith",
+    "visibility_level":0,
+    "path_with_namespace":"jsmith/example",
+    "default_branch":"master",
+    "homepage":"http://example.com/jsmith/example",
+    "url":"git@example.com:jsmith/example.git",
+    "ssh_url":"git@example.com:jsmith/example.git",
+    "http_url":"http://example.com/jsmith/example.git"
+  },
+  "changes": [
+    {
+      "before":"8205ea8d81ce0c6b90fbe8280d118cc9fdad6130",
+      "after":"4045ea7a3df38697b3730a20fb73c8bed8a3e69e",
+      "ref":"refs/heads/master"
+    }
+  ],
+  "refs":["refs/heads/master"]
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/tag-push-system-hook-event.json b/src/test/resources/org/gitlab4j/api/tag-push-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..f453bd63b70722f983a9fe2f949393b0369c5736
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/tag-push-system-hook-event.json
@@ -0,0 +1,37 @@
+{
+  "event_name": "tag_push",
+  "before": "0000000000000000000000000000000000000000",
+  "after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
+  "ref": "refs/tags/v1.0.0",
+  "checkout_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e",
+  "user_id": 1,
+  "user_name": "John Smith",
+  "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+  "project_id": 1,
+  "project":{
+    "name":"Example",
+    "description":"",
+    "web_url":"http://example.com/jsmith/example",
+    "git_ssh_url":"git@example.com:jsmith/example.git",
+    "git_http_url":"http://example.com/jsmith/example.git",
+    "namespace":"Jsmith",
+    "visibility_level":0,
+    "path_with_namespace":"jsmith/example",
+    "default_branch":"master",
+    "homepage":"http://example.com/jsmith/example",
+    "url":"git@example.com:jsmith/example.git",
+    "ssh_url":"git@example.com:jsmith/example.git",
+    "http_url":"http://example.com/jsmith/example.git"
+  },
+  "repository":{
+    "name": "Example",
+    "url": "ssh://git@example.com/jsmith/example.git",
+    "description": "",
+    "homepage": "http://example.com/jsmith/example",
+    "git_http_url":"http://example.com/jsmith/example.git",
+    "git_ssh_url":"git@example.com:jsmith/example.git",
+    "visibility_level":0
+  },
+  "commits": [],
+  "total_commits_count": 0
+}
\ No newline at end of file
diff --git a/src/test/resources/org/gitlab4j/api/user-system-hook-event.json b/src/test/resources/org/gitlab4j/api/user-system-hook-event.json
new file mode 100644
index 0000000000000000000000000000000000000000..9e5e69852450b7cce76f9c1ed18b288d53162b3a
--- /dev/null
+++ b/src/test/resources/org/gitlab4j/api/user-system-hook-event.json
@@ -0,0 +1,10 @@
+{
+    "event_name": "user_rename",
+    "created_at": "2017-11-01T11:21:04Z",
+    "updated_at": "2017-11-01T14:04:47Z",
+          "name": "new-name",
+         "email": "best-email@example.tld",
+       "user_id": 58,
+      "username": "new-exciting-name",
+  "old_username": "old-boring-name"
+}
\ No newline at end of file