SearchStack.PublicApi
2.2.0
See the version list below for details.
dotnet add package SearchStack.PublicApi --version 2.2.0
NuGet\Install-Package SearchStack.PublicApi -Version 2.2.0
<PackageReference Include="SearchStack.PublicApi" Version="2.2.0" />
<PackageVersion Include="SearchStack.PublicApi" Version="2.2.0" />
<PackageReference Include="SearchStack.PublicApi" />
paket add SearchStack.PublicApi --version 2.2.0
#r "nuget: SearchStack.PublicApi, 2.2.0"
#:package SearchStack.PublicApi@2.2.0
#addin nuget:?package=SearchStack.PublicApi&version=2.2.0
#tool nuget:?package=SearchStack.PublicApi&version=2.2.0
SearchStack.PublicApi
The official .NET client for the Search Stack public
API — search, ingest, and manage your indexes from any .NET app. Typed,
HttpClient-based, with near-zero dependencies.
A typed client for the Search Stack public API (api.searchstack.dev). It exposes
a SearchStackClient with a service per area of the API and request/response types
that match the API's JSON wire format (snake_case) one-to-one, covering the full
public surface — search and suggest, list/group management and versioning,
ingestion, evals and judges, analytics, and account details.
This is the C# counterpart of the @searchstack/public-api
TypeScript package and mirrors its surface closely.
Targets & dependencies
Multi-targets netstandard2.0 (works on .NET Framework 4.6.1+, Mono, Xamarin,
Unity, .NET Core 2.0+) and net8.0. The only dependency is System.Text.Json,
and that is pulled in only on netstandard2.0 — on net8.0 it is in-box, so
the package has zero transitive dependencies there.
Install
dotnet add package SearchStack.PublicApi
Quickstart
using SearchStack.PublicApi;
var client = new SearchStackClient("sk_live_...");
// Search version 1 of the "products" list in the "acme" account.
var result = await client.Search.SearchListAsync("acme", "products", 1,
new SearchOptions { Query = "running shoes", Size = 10 });
if (result.IsSuccess)
{
foreach (var hit in result.ToSuccess().Results)
Console.WriteLine($"{hit.Name}: {string.Join(", ", hit.Fields.Keys)}");
}
else
{
// Methods never throw — errors come back as a typed Problem (see below).
Console.Error.WriteLine($"{result.ToProblem().Status}: {result.ToProblem().Detail}");
}
Authentication
The API accepts either of two credentials. Configure one when constructing the client:
using SearchStack.PublicApi;
// API key -> sent as the `X-API-Key` header
var client = new SearchStackClient("sk_live_...");
// or, with full options:
var client = new SearchStackClient(new SearchStackClientOptions
{
AccessToken = "eyJ...", // sent as Authorization: Bearer <token>
BaseUrl = "https://api.searchstack.dev/", // optional, defaults to production
});
If both an API key and an access token are supplied, the access token takes precedence. Credentials can be swapped at runtime (e.g. after refreshing a token):
client.SetAccessToken(newToken);
client.SetApiKey(newKey);
Bring your own HttpClient
By default the client creates and owns an HttpClient (disposed with the client).
To control handlers, pooling or timeouts — or to use IHttpClientFactory — pass
your own; it will not be disposed by the client:
var client = new SearchStackClient(new SearchStackClientOptions
{
ApiKey = "sk_live_...",
HttpClient = httpClientFactory.CreateClient("searchstack"),
});
Result handling
No method throws on an HTTP error. Each resolves to a Response<T> (or Response
for no-body calls) that is either a success carrying the typed payload or a
Problem (RFC 7807). Network and JSON errors are surfaced as a Problem with
Status 500. Cancellation still throws OperationCanceledException.
var result = await client.Search.SearchListAsync("acme", "products", 1,
new SearchOptions { Query = "boots" });
if (result.IsSuccess)
{
SearchResponse page = result.ToSuccess();
Console.WriteLine($"{page.TotalCount}, {page.Results.Count}");
}
else
{
Problem problem = result.ToProblem();
Console.Error.WriteLine($"{problem.Status}: {problem.Detail}");
}
result.Data and result.Problem are also exposed directly for pattern-style
checks.
Services
| Property | Service | Highlights |
|---|---|---|
client.Accounts |
Account | GetAsync, GetNameAsync |
client.Lists |
List | CreateAsync, GetAsync, EditAsync, RestoreVersionAsync, DeleteAsync |
client.Groups |
Group | CreateAsync, GetAsync, GetVersionsAsync, GetVersionMembersAsync, UpdateAsync, CloneAsync, BumpVersionAsync, RestoreVersionAsync, AddListAsync, RemoveListAsync, SetModelAsync, RemoveModelAsync, SetRerankerAsync, RemoveRerankerAsync, AddIpAddressAsync, RemoveIpAddressAsync, TransferAsync, DeleteAsync |
client.Facets |
Facet | CreateAsync, RenameAsync, RemoveAsync |
client.Resources |
Resource | CreateAsync, RenameAsync, RemoveAsync |
client.Searchables |
Searchable field | CreateAsync, RenameAsync, RemoveAsync |
client.Contributors |
Contributor | AddAsync, RemoveAsync |
client.Coordinates |
Coordinates | AddAsync, RemoveAsync |
client.MediaStores |
Media store | DeleteMediaAsync |
client.SearchResults |
Search result writes | CreateAsync, BulkInsertAsync, BulkInsertWithFieldsAsync, EditAsync, EditVectorAsync, RemoveAsync, DeleteByFilterAsync, SoftDeleteByFilterAsync |
client.Search |
Search / query | SearchListAsync, SearchGroupAsync, RelatedAsync, SearchListByImageAsync, SearchGroupByImageAsync, SearchListByImageBase64Async, SearchGroupByImageBase64Async, ExtractDocumentTextAsync, RecordListClickAsync, RecordGroupClickAsync |
client.Suggest |
Suggest | ListAsync, GroupAsync |
client.Analytics |
Analytics | GetListAsync, GetGroupAsync |
client.Evals |
Eval sets | ListAsync, GetAsync, GetRunsAsync, GetRunStatusAsync, CreateAsync, BootstrapAsync, RunAsync, DeleteAsync |
client.Judges |
Judges | ListAsync, GetAsync, GetRunStatusAsync, CreateAsync, RunAsync, TryAsync, DeleteAsync |
client.Discovery |
Discovery (anonymous) | InfoAsync, ExamplesAsync, CatalogAsync |
Search and suggest methods use the API's
POSTvariants so options are passed as a typed object rather than a hand-built query string.
Examples
Text search a list version:
var res = await client.Search.SearchListAsync("acme", "products", 3, new SearchOptions
{
Query = "running shoes",
Size = 20,
Filter = "brand eq 'Acme'",
MinimumTextScore = 0.6,
});
Find related results and record a click-through:
var related = await client.Search.RelatedAsync("acme", "products", "sku-123",
new RelatedOptions { Size = 5 });
if (related.IsSuccess)
{
var page = related.ToSuccess();
if (!string.IsNullOrEmpty(page.QueryId))
{
await client.Search.RecordListClickAsync("acme", "products", new RecordClickRequest
{
QueryId = page.QueryId!,
ResultId = page.Results[0].Name,
});
}
}
Bulk insert documents:
await client.SearchResults.BulkInsertWithFieldsAsync("acme", "products", new[]
{
new Dictionary<string, object?> { ["search_result_name"] = "sku-1", ["title"] = "Trail Shoe", ["price"] = 99 },
new Dictionary<string, object?> { ["search_result_name"] = "sku-2", ["title"] = "Road Shoe", ["price"] = 79 },
});
Manage a group and its membership versions:
await client.Groups.AddListAsync("acme", "catalog",
new AddListToGroupRequest { ListName = "products", Version = 4 });
await client.Groups.BumpVersionAsync("acme", "catalog"); // pin members to their latest
var versions = await client.Groups.GetVersionsAsync("acme", "catalog");
// search a specific, frozen membership version:
await client.Search.SearchGroupAsync("acme", "catalog",
versions.ToSuccess().CurrentVersion, new SearchOptions { Query = "boots" });
Try a judge, then track search quality with an eval set:
var verdict = await client.Judges.TryAsync("acme", "relevance-judge", new TryJudgeRequest
{
Context = new JudgeContextDto { Text = "waterproof hiking boots" },
Candidate = new JudgeCandidateDto { Id = "sku-1", Text = "Trail Runner — mesh, not waterproof" },
});
if (verdict.IsSuccess) Console.WriteLine(verdict.ToSuccess().Passed);
var run = await client.Evals.RunAsync("acme", "relevance"); // async (202)
if (run.IsSuccess)
{
var status = await client.Evals.GetRunStatusAsync("acme", "relevance", run.ToSuccess().RunId);
}
List analytics for a date range:
var report = await client.Analytics.GetListAsync("acme", "products", "2026-05-01", "2026-05-31");
Development
dotnet build
dotnet pack -c Release
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 8.0.5)
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.