diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj
index 697ae2e1e43..dea850154e7 100644
--- a/src/Nest/Nest.csproj
+++ b/src/Nest/Nest.csproj
@@ -1084,6 +1084,9 @@
+
+
+
diff --git a/src/Nest/Search/SearchTemplate/RenderSearchTemplate/ElasticClient-RenderSearchTemplate.cs b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/ElasticClient-RenderSearchTemplate.cs
new file mode 100644
index 00000000000..95dae3012e3
--- /dev/null
+++ b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/ElasticClient-RenderSearchTemplate.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Threading.Tasks;
+using Elasticsearch.Net;
+
+namespace Nest
+{
+ public partial interface IElasticClient
+ {
+ ///
+ IRenderSearchTemplateResponse RenderSearchTemplate(Func selector);
+
+ ///
+ IRenderSearchTemplateResponse RenderSearchTemplate(IRenderSearchTemplateRequest request);
+
+ ///
+ Task RenderSearchTemplateAsync(Func selector);
+
+ ///
+ Task RenderSearchTemplateAsync(IRenderSearchTemplateRequest request);
+ }
+ public partial class ElasticClient
+ {
+ public IRenderSearchTemplateResponse RenderSearchTemplate(Func selector) =>
+ this.RenderSearchTemplate(selector.InvokeOrDefault(new RenderSearchTemplateDescriptor()));
+
+ public IRenderSearchTemplateResponse RenderSearchTemplate(IRenderSearchTemplateRequest request) =>
+ this.Dispatcher.Dispatch(
+ request,
+ (p, d) => this.LowLevelDispatch.RenderSearchTemplateDispatch(p, d)
+ );
+
+ public Task RenderSearchTemplateAsync(Func selector) =>
+ this.RenderSearchTemplateAsync(selector.InvokeOrDefault(new RenderSearchTemplateDescriptor()));
+
+ public Task RenderSearchTemplateAsync(IRenderSearchTemplateRequest request) =>
+ this.Dispatcher.DispatchAsync(
+ request,
+ (p, d) => this.LowLevelDispatch.RenderSearchTemplateDispatchAsync(p, d)
+ );
+ }
+}
diff --git a/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateRequest.cs b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateRequest.cs
new file mode 100644
index 00000000000..7d632840696
--- /dev/null
+++ b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateRequest.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace Nest
+{
+ public partial interface IRenderSearchTemplateRequest
+ {
+ [JsonProperty("inline")]
+ string Inline { get; set; }
+
+ [JsonProperty("file")]
+ string File { get; set; }
+
+ [JsonProperty("params")]
+ [JsonConverter(typeof(VerbatimDictionaryKeysJsonConverter))]
+ Dictionary Params { get; set; }
+
+ }
+
+ public partial class RenderSearchTemplateRequest
+ {
+ public string Inline { get; set; }
+ public string File { get; set; }
+ public Dictionary Params { get; set; }
+ }
+
+
+ public partial class RenderSearchTemplateDescriptor
+ {
+ string IRenderSearchTemplateRequest.Inline { get; set; }
+ string IRenderSearchTemplateRequest.File { get; set; }
+ Dictionary IRenderSearchTemplateRequest.Params { get; set; }
+
+ public RenderSearchTemplateDescriptor Inline(string inline) => Assign(a => a.Inline = inline);
+
+ public RenderSearchTemplateDescriptor File(string file) => Assign(a => a.File = file);
+
+ public RenderSearchTemplateDescriptor Params(Dictionary scriptParams) => Assign(a => a.Params = scriptParams);
+
+ public RenderSearchTemplateDescriptor Params(Func, FluentDictionary> paramsSelector) =>
+ Assign(a => a.Params = paramsSelector?.Invoke(new FluentDictionary()));
+
+ }
+}
diff --git a/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateResponse.cs b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateResponse.cs
new file mode 100644
index 00000000000..dda80009aca
--- /dev/null
+++ b/src/Nest/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateResponse.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace Nest
+{
+ public interface IRenderSearchTemplateResponse : IResponse
+ {
+ ILazyDocument TemplateOutput { get; set; }
+ }
+
+ [JsonObject]
+ public class RenderSearchTemplateResponse : ResponseBase, IRenderSearchTemplateResponse
+ {
+ [JsonProperty("template_output")]
+ public ILazyDocument TemplateOutput { get; set; }
+ }
+}
diff --git a/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateApiTests.cs b/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateApiTests.cs
new file mode 100644
index 00000000000..22394437e58
--- /dev/null
+++ b/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateApiTests.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Elasticsearch.Net;
+using FluentAssertions;
+using Nest;
+using Tests.Framework;
+using Tests.Framework.Integration;
+using Xunit;
+
+namespace Tests.Search.SearchTemplate.RenderSearchTemplate
+{
+ [Collection(IntegrationContext.ReadOnly)]
+ public class RenderSearchTemplateApiTests : ApiIntegrationTestBase
+ {
+ public RenderSearchTemplateApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
+
+ protected override LazyResponses ClientUsage() => Calls(
+ fluent: (c, f) => c.RenderSearchTemplate(f),
+ fluentAsync: (c, f) => c.RenderSearchTemplateAsync(f),
+ request: (c, r) => c.RenderSearchTemplate(r),
+ requestAsync: (c, r) => c.RenderSearchTemplateAsync(r)
+ );
+
+ protected override HttpMethod HttpMethod => HttpMethod.POST;
+ protected override string UrlPath => $"/_render/template";
+ protected override int ExpectStatusCode => 200;
+ protected override bool ExpectIsValid => true;
+
+ private static string inlineSearchTemplate = @"
+{
+ ""query"": {
+ ""terms"": {
+ ""status"": [
+ ""{{#status}}"",
+ ""{{.}}"",
+ ""{{/status}}""
+ ]
+ }
+ }
+ }";
+ private string[] statusValues = new[] { "pending", "published" };
+
+ protected override Func Fluent => s=>s
+ .Inline(inlineSearchTemplate)
+ .Params(p=>p
+ .Add("status", statusValues)
+ );
+
+
+ protected override RenderSearchTemplateRequest Initializer => new RenderSearchTemplateRequest
+ {
+ Inline = inlineSearchTemplate,
+ Params = new Dictionary
+ {
+ { "status", statusValues }
+ }
+ };
+
+ [I] public Task AssertResponse() => this.AssertOnAllResponses(r =>
+ {
+ r.TemplateOutput.Should().NotBeNull();
+ var searchRequest = r.TemplateOutput.As();
+ searchRequest.Should().NotBeNull();
+
+ searchRequest.Query.Should().NotBeNull();
+ });
+ }
+}
diff --git a/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateUrlTests.cs b/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateUrlTests.cs
new file mode 100644
index 00000000000..eb30e485847
--- /dev/null
+++ b/src/Tests/Search/SearchTemplate/RenderSearchTemplate/RenderSearchTemplateUrlTests.cs
@@ -0,0 +1,28 @@
+using System.Threading.Tasks;
+using Nest;
+using Tests.Framework;
+using static Tests.Framework.UrlTester;
+
+namespace Tests.Search.SearchTemplate.RenderSearchTemplate
+{
+ public class RenderSearchTemplateUrlTests
+ {
+ [U] public async Task Urls()
+ {
+ var id = "the-id";
+ await POST("/_render/template/the-id")
+ .Fluent(c => c.RenderSearchTemplate(s=>s.Id(id)))
+ .Request(c=>c.RenderSearchTemplate(new RenderSearchTemplateRequest(id)))
+ .FluentAsync(c => c.RenderSearchTemplateAsync(s=>s.Id(id)))
+ .RequestAsync(c=>c.RenderSearchTemplateAsync(new RenderSearchTemplateRequest(id)))
+ ;
+
+ await POST("/_render/template")
+ .Fluent(c => c.RenderSearchTemplate(s=>s.Inline("")))
+ .Request(c=>c.RenderSearchTemplate(new RenderSearchTemplateRequest { Inline = "" }))
+ .FluentAsync(c => c.RenderSearchTemplateAsync(s=>s.Inline("")))
+ .RequestAsync(c=>c.RenderSearchTemplateAsync(new RenderSearchTemplateRequest { Inline = "" }))
+ ;
+ }
+ }
+}
diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj
index 8c21a58c266..3972334d63a 100644
--- a/src/Tests/Tests.csproj
+++ b/src/Tests/Tests.csproj
@@ -545,6 +545,8 @@
+
+