Loading

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 NewTyped function with option values:

client, err := elasticsearch.NewTyped(
    elasticsearch.WithAddresses("https://localhost:9200"),
    elasticsearch.WithAPIKey("your-api-key"),
)
if err != nil {
    log.Fatal(err)
}
defer client.Close(context.Background())
		
  1. The Elasticsearch node URL(s).
  2. Authentication credentials (API key, username/password, or service token).
  3. 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["New - Low-level API"]
        TC["NewTyped - Typed API"]
    end

    subgraph shared [Shared Infrastructure]
        OPTS["Options - WithAddresses, WithAPIKey, ..."]
        TP["Transport - retry, compression, node selection"]
    end

    LC --> OPTS
    TC --> OPTS
    OPTS --> TP

Because both clients implement the same transport interface, individual typed endpoint packages (typedapi/core/search, typedapi/indices/create, ...) accept either client type. That means you can mix the two styles in a single application, and you can migrate existing low-level code to the typed API one endpoint at a time. If you already hold a *elasticsearch.Client and want the full typed surface without rebuilding the transport, call client.ToTyped(). See the migration guide for details on both approaches.

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.NewTyped(
    // 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.
}
		
  1. Create a bulk request builder.
  2. Append an index operation with metadata and document body.
  3. 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.