Typed API
The typed API provides a strongly typed Go API for Elasticsearch, designed with Go structs and the runtime in mind. Requests and responses are modeled as Go types, giving you compile-time safety, IDE autocompletion, and no need to manually parse JSON.
The code is generated from the elasticsearch-specification.
Create a typed client using the NewTypedClient function. It accepts the same elasticsearch.Config as the low-level client:
client, err := elasticsearch.NewTypedClient(elasticsearch.Config{
Addresses: []string{"https://localhost:9200"},
APIKey: "your-api-key",
})
if err != nil {
log.Fatal(err)
}
defer client.Close(context.Background())
- The Elasticsearch node URL(s).
- Authentication credentials (API key, username/password, or service token).
- Always close the client when done to release resources.
For full configuration options, see the Configuration reference.
The typed client and the low-level client share the same underlying transport, configuration, and connection pool. The typed API is a higher-level abstraction built on top of the same infrastructure:
graph TB
subgraph clients [Client Layer]
LC["NewClient - Low-level API"]
TC["NewTypedClient - Typed API"]
end
subgraph shared [Shared Infrastructure]
CFG["elasticsearch.Config"]
TP["Transport - retry, compression, node selection"]
end
LC --> CFG
TC --> CFG
CFG --> TP
You can use both clients in the same application since they share the same transport. Choose the typed API for compile-time safety, or fall back to the low-level API for maximum flexibility.
The typed client organizes Elasticsearch APIs into namespaces that mirror the REST API structure. Each namespace groups related operations:
graph LR
TC["TypedClient"]
subgraph common [Common Operations]
Core
Indices
Cluster
Cat
end
subgraph search_ns [Search and Analytics]
Search["Core.Search"]
Esql
Eql
Sql
AsyncSearch
end
subgraph ingest_ns [Data Ingestion]
Bulk["Core.Bulk"]
Ingest
Transform
end
subgraph management [Management]
Security
Ml
Snapshot
Slm
Ilm
end
TC --> common
TC --> search_ns
TC --> ingest_ns
TC --> management
Access API methods through the namespace fields on the client:
// Indices namespace
client.Indices.Create("my-index").Do(context.Background())
// Cluster namespace
client.Cluster.Health().Do(context.Background())
// Core namespace (also available directly on the client)
client.Search().Index("my-index").Do(context.Background())
// Security namespace
client.Security.GetUser("admin").Do(context.Background())
// ML namespace
client.Ml.GetJobs().Do(context.Background())
The full list of namespaces includes:
AsyncSearch, Autoscaling, Cat, Ccr, Cluster, Connector, Core,
DanglingIndices, Enrich, Eql, Esql, Features, Fleet, Graph,
Ilm, Indices, Inference, Ingest, License, Logstash, Migration,
Ml, Monitoring, Nodes, Profiling, QueryRules, Rollup,
SearchApplication, SearchableSnapshots, Security, Shutdown, Simulate,
Slm, Snapshot, Sql, Ssl, Streams, Synonyms, Tasks,
TextStructure, Transform, Watcher, and Xpack.
The typed API includes endpoints that use NDJSON bodies such as bulk and msearch.
For example, you can build a bulk request by appending operations and then executing it:
client, err := elasticsearch.NewTypedClient(elasticsearch.Config{
// Proper configuration for your Elasticsearch cluster.
})
if err != nil {
// Handle error.
}
index := "my-index"
id := "1"
bulk := client.Bulk()
if err := bulk.IndexOp(types.IndexOperation{Index_: &index, Id_: &id}, map[string]any{"title": "Test"}); err != nil {
// Handle error.
}
res, err := bulk.Do(context.Background())
if err != nil {
// Handle error.
}
if res.Errors {
// One or more operations failed.
}
- Create a bulk request builder.
- Append an index operation with metadata and document body.
- Execute the bulk request and check for errors.
If you already have a newline-delimited JSON payload, you can submit it directly with Raw(io.Reader) on the request builder.
- Conventions — Naming, structure, enums, and unions in the typed API
- esdsl builders — Fluent DSL builders for queries, aggregations, mappings, and sort options
- Using the API — Practical examples comparing both API styles