diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 32c1bfaf5c..5f846a4174 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -86,6 +86,7 @@
+
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
new file mode 100644
index 0000000000..a3d2285297
--- /dev/null
+++ b/MediaBrowser.Api/SearchService.cs
@@ -0,0 +1,192 @@
+using System.Collections;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Search;
+using ServiceStack.ServiceHost;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace MediaBrowser.Api
+{
+ ///
+ /// Class GetSearchHints
+ ///
+ [Route("/Search/Hints", "GET")]
+ [Api(Description = "Gets search hints based on a search term")]
+ public class GetSearchHints : IReturn>
+ {
+ ///
+ /// Skips over a given number of items within the results. Use for paging.
+ ///
+ /// The start index.
+ [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? StartIndex { get; set; }
+
+ ///
+ /// The maximum number of items to return
+ ///
+ /// The limit.
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+
+ ///
+ /// Gets or sets the user id.
+ ///
+ /// The user id.
+ [ApiMember(Name = "UserId", Description = "Optional. Supply a user id to search within a user's library or omit to search all.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public Guid? UserId { get; set; }
+
+ ///
+ /// Search characters used to find items
+ ///
+ /// The index by.
+ [ApiMember(Name = "SearchTerm", Description = "The search term to filter on", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string SearchTerm { get; set; }
+ }
+
+ ///
+ /// Class SearchService
+ ///
+ public class SearchService : BaseApiService
+ {
+ ///
+ /// The _user manager
+ ///
+ private readonly IUserManager _userManager;
+ ///
+ /// The _search engine
+ ///
+ private readonly ILibrarySearchEngine _searchEngine;
+ private readonly ILibraryManager _libraryManager;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The user manager.
+ /// The search engine.
+ /// The library manager.
+ public SearchService(IUserManager userManager, ILibrarySearchEngine searchEngine, ILibraryManager libraryManager)
+ {
+ _userManager = userManager;
+ _searchEngine = searchEngine;
+ _libraryManager = libraryManager;
+ }
+
+ ///
+ /// Gets the specified request.
+ ///
+ /// The request.
+ /// System.Object.
+ public object Get(GetSearchHints request)
+ {
+ var result = GetSearchHintsAsync(request).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ ///
+ /// Gets the search hints async.
+ ///
+ /// The request.
+ /// Task{IEnumerable{SearchHintResult}}.
+ private async Task> GetSearchHintsAsync(GetSearchHints request)
+ {
+ IEnumerable inputItems;
+
+ if (request.UserId.HasValue)
+ {
+ var user = _userManager.GetUserById(request.UserId.Value);
+
+ inputItems = user.RootFolder.GetRecursiveChildren(user);
+ }
+ else
+ {
+ inputItems = _libraryManager.RootFolder.RecursiveChildren;
+ }
+
+ var results = await _searchEngine.GetSearchHints(inputItems, request.SearchTerm).ConfigureAwait(false);
+
+ if (request.StartIndex.HasValue)
+ {
+ results = results.Skip(request.StartIndex.Value);
+ }
+
+ if (request.Limit.HasValue)
+ {
+ results = results.Take(request.Limit.Value);
+ }
+
+ return results.Select(GetSearchHintResult);
+ }
+
+ ///
+ /// Gets the search hint result.
+ ///
+ /// The item.
+ /// SearchHintResult.
+ private SearchHintResult GetSearchHintResult(BaseItem item)
+ {
+ var result = new SearchHintResult
+ {
+ Name = item.Name,
+ IndexNumber = item.IndexNumber,
+ ParentIndexNumber = item.ParentIndexNumber,
+ ItemId = DtoBuilder.GetClientItemId(item),
+ Type = item.GetType().Name,
+ MediaType = item.MediaType
+ };
+
+ if (item.HasImage(ImageType.Primary))
+ {
+ result.PrimaryImageTag = Kernel.Instance.ImageManager.GetImageCacheTag(item, ImageType.Primary, item.GetImage(ImageType.Primary));
+ }
+
+ var episode = item as Episode;
+
+ if (episode != null)
+ {
+ result.Series = episode.Series.Name;
+ }
+
+ var season = item as Season;
+
+ if (season != null)
+ {
+ result.Series = season.Series.Name;
+ }
+
+ var album = item as MusicAlbum;
+
+ if (album != null)
+ {
+ var songs = album.Children.OfType