         /* Event codes */
         private static const TOKEN_RECEIVED:String = "tokenReceived";
         private static const NOTIFICATION_RECEIVED:String = "notificationReceived";
+        private static const TAGS_RECEIVED:String = "tagsReceived";
 
         /* Callbacks */
         private static var mTokenCallbacks:Vector.<Function> = new <Function>[];
         private static var mNotificationCallbacks:Vector.<Function> = new <Function>[];
+        private static var mCallbackMap:Dictionary;
+        private static var mCallbackIdCounter:int;
 
         /* Misc */
         private static var mInitialized:Boolean;

    import flash.events.StatusEvent;
    import flash.external.ExtensionContext;
    import flash.system.Capabilities;

    public class OneSignal {


                        mNotificationCallbacks[i]( OneSignalNotification.fromJSON( responseJSON ) );
                    }
                    return;
                case TAGS_RECEIVED:
                    responseJSON = JSON.parse( event.level );
                    var callbackID:int = ("callbackID" in responseJSON) ? responseJSON.callbackID : -1;
                    var callback:Function = getCallback( callbackID );
                    if( callback !== null ) {
                        var tags:Object = responseJSON.tags;
                        if( tags is String ) {
                            tags = JSON.parse( tags as String );
                        }
                        callback( tags );
                    }
                    return;
            }
        }

        /**
         * Registers given callback and generates ID which is used to look the callback up when it is time to call it.
         * @param callback Function to register.
         * @return ID of the callback.
         */
        private static function registerCallback( callback:Function ):int {
            if( callback == null ) return -1;

            mCallbackMap[mCallbackIdCounter] = callback;
            return mCallbackIdCounter++;
        }

        /**
         * Gets registered callback with given ID.
         * @param callbackID ID of the callback to retrieve.
         * @return Callback registered with given ID, or <code>null</code> if no such callback exists.
         */
        private static function getCallback( callbackID:int ):Function {
            if( callbackID == -1 || !(callbackID in mCallbackMap) ) return null;
            return mCallbackMap[callbackID];
        }

        /**
         * Unregisters callback with given ID.
         * @param callbackID ID of the callback to unregister.
         */
        private static function unregisterCallback( callbackID:int ):void {
            if( callbackID in mCallbackMap ) {
                delete mCallbackMap[callbackID];
            }
        }

        /**
         * Returns list of key-values from key-value object, e.g. { "key": "val" } -> [ "key", "val" ].
         * @param object Key-value object to transform into list.
         * @return List of key-values from <code>object</code>, or null if <code>object</code> is null.
         */
        private static function getVectorFromObject( object:Object ):Vector.<String> {
            var properties:Vector.<String> = null;
            if( object ) {
                properties = new <String>[];
                /* Create a list of object properties, that is key followed by its value */
                for( var key:String in object ) {
                    properties[properties.length] = key;
                    properties[properties.length] = object[key];
                }
            }
            return properties;
        }

        private static function log( message:String ):void {
