/// <summary>
        /// Get a history of notifications of current API client. History items are stored for 24 hours.
        /// <remarks>User API key usage permitted if subscribe permission is added through apikey.authorize().</remarks>
        /// </summary>
        /// <param name="sinceId">If specified, will only return data with id higher than since_id (newer).</param>
        /// <param name="sinceTime">String with date. If specified, will only return data with timestamp after specified value (newer).</param>
        /// <param name="limit">Maximum number of history items to get. Default and max: 100.</param>
        /// <param name="order">Order of data that will be returned.</param>
        /// <returns>List of History objects.</returns>
        public async Task <List <History> > GetHistory(string sinceId        = null, DateTime?sinceTime = null, int limit = MaxLimit,
                                                       DataObjectOrder order = DataObjectOrder.Ascending)
        {
            if (limit > MaxLimit || limit < 1)
            {
                throw new ArgumentException();
            }

            return
                (await
                 _syncanoClient.GetAsync <List <History> >("notification.get_history",
                                                           new
            {
                since_id = sinceId,
                since_time = sinceTime,
                limit,
                order = DataObjectOrderStringConverter.GetString(order)
            }, "history"));
        }
        /// <summary>
        /// Get data from collection(s) or whole project with optional additional filtering. All filters, unless explicitly noted otherwise, affect all hierarchy levels. To paginate and to get more data, use since parameter.
        /// <remarks>The collection_id/collection_key parameter means that one can use either one of them - collection_id or collection_key.</remarks>
        /// <remarks>User API key usage permitted. Returns Data Objects that are in a container with a read_data permission and associated with current user Data Objects that are in a container with a read_own_data permission.</remarks>
        /// </summary>
        /// <param name="request">Request for querying data objects.</param>
        /// <returns>List of DataObject objects.</returns>
        public async Task <List <DataObject> > Get(DataObjectRichQueryRequest request)
        {
            if (request.ProjectId == null)
            {
                throw new ArgumentNullException();
            }

            if (request.CollectionId == null && request.CollectionKey == null)
            {
                throw new ArgumentNullException();
            }

            if (request.Limit > MaxVauluesPerRequest || request.Limit < 0)
            {
                throw new ArgumentException();
            }

            if (request.ChildrenLimit > MaxVauluesPerRequest || request.ChildrenLimit < 0)
            {
                throw new ArgumentException();
            }

            var dataIds = request.DataIds == null ? new List <string>() : new List <string>(request.DataIds);

            if (dataIds.Count + (request.DataId != null ? 1 : 0) > MaxVauluesPerRequest)
            {
                throw new ArgumentException();
            }
            if (request.DataId != null)
            {
                dataIds.Add(request.DataId);
            }

            var folders = request.Folders == null ? new List <string>() : new List <string>(request.Folders);

            if (folders.Count + (request.Folder != null ? 1 : 0) >
                MaxVauluesPerRequest)
            {
                throw new ArgumentException();
            }
            if (request.Folder != null)
            {
                folders.Add(request.Folder);
            }

            var parentIds = request.ParentIds == null ? new List <string>() : new List <string>(request.ParentIds);

            if (parentIds.Count + (request.ParentId != null ? 1 : 0) > MaxVauluesPerRequest)
            {
                throw new ArgumentException();
            }
            if (request.ParentId != null)
            {
                parentIds.Add(request.ParentId);
            }

            var childIds = request.ChildIds == null ? new List <string>() : new List <string>(request.ChildIds);

            if (childIds.Count + (request.ChildId != null ? 1 : 0) > MaxVauluesPerRequest)
            {
                throw new ArgumentException();
            }
            if (request.ChildId != null)
            {
                childIds.Add(request.ChildId);
            }

            var parameters = new
            {
                project_id       = request.ProjectId,
                collection_id    = request.CollectionId,
                collection_key   = request.CollectionKey,
                data_ids         = dataIds.Count == 0 ? null : dataIds.ToArray(),
                state            = request.State.ToString(),
                folders          = folders.Count == 0 ? null : folders.ToArray(),
                since            = request.Since == null ? request.SinceId == null ? null : request.SinceId.Value.ToString(CultureInfo.InvariantCulture) : request.Since.Value.ToString(),
                max_id           = request.MaxId,
                limit            = request.Limit,
                order            = DataObjectOrderStringConverter.GetString(request.Order),
                order_by         = DataObjectOrderByStringConverter.GetString(request.OrderBy),
                filter           = request.Filter == null ? null : request.Filter.ToString(),
                include_children = request.IncludeChildren,
                depth            = request.Depth,
                children_limit   = request.ChildrenLimit,
                parent_ids       = parentIds.ToArray(),
                child_ids        = childIds.ToArray(),
                by_user          = request.ByUser,
                dataFilters      = request.DataFieldFilters.ToDictionary(pair => pair.Key, pair => pair.Value)
            };


            return
                (await
                 _syncanoClient.PostAsync <List <DataObject> >("data.get",
                                                               parameters, "data"));
        }