Elasticsearch is organized around a cluster of nodes that store and serve indices (and data streams). Most operations target one of these core entities: indices/data streams, documents (by id), snapshots/repositories, long‑running tasks (identified by task_id), transforms, ML jobs, and inference endpoints. Understanding which ID each family needs and which call returns it is the single most important operational pattern.
Key entities and relationships
-
Indices and data streams: indices (strings) are the primary storage unit. Data streams are collections of backing indices; many APIs accept either
indexordata_streamnames and special options for expand/ignore behavior. Aliases map names to one or more indices and are commonly used for rollover workflows. -
Documents: documents live in an index and are addressed by
index+id. Most write/read flows need the index name and optionally anid. -
Templates / component templates: templates define mappings/settings/aliases applied when new indices/data streams are created. Component templates are composed into index templates.
-
Ingest pipelines: named pipelines preprocess documents during indexing. Create with a pipeline API and reference by
pipelinewhen indexing or in bulk operations. -
Snapshots & repositories: snapshots are stored in repositories. You must create/configure a
repositorybefore creating snapshots. Snapshots are referred to byrepository+snapshotname. -
Long-running jobs and tasks: many heavy operations (reindex, update-by-query, delete-by-query, reindexing, snapshot restore, ML jobs, transforms) either accept a
wait_for_completionflag or return atask_idyou can inspect and rethrottle. Async search and async ES|QL follow a submit→poll→delete lifecycle and return their ownid. -
Machine Learning and transforms: ML jobs (
job_id,datafeed_id) and trained models (model_id) have their own create/start/stop/status flows. Transforms are created/started/stopped bytransform_id. -
Inference endpoints: inference endpoints are created with an
inference_idand then invoked for embeddings, completions, rerank, etc. Many endpoint types (OpenAI, Anthropic, etc.) share the same semantics but require appropriatetask_typewhen creating.
What to call first — common entry points
Start by fetching the cluster and index identifiers you'll need: use cluster-info/cluster-health to check cluster status and indices-get or cat-indices to list indices and get canonical index names. To find data stream names use indices-get-data-stream.
- Need an index name for most operations: call
indices-getorindices-resolve-index. - Need a repository or snapshot name: call
snapshot-get-repositorythensnapshot-get. - Need a transform / job / model id: call the
transform-get-transform,ml-get-jobs, orml-get-trained-modelsendpoints respectively to list available IDs. - For connectors or inference endpoints: list them (
connector-list,inference-get) to obtainconnector_idorinference_id.
Knowing where to obtain the small set of IDs the rest of your flow requires prevents dead ends.
Common capabilities and practical sequences
Below are the real tasks users ask agents to perform and the practical API sequences to accomplish them. Each step uses the API parameter names you must supply (index, id, repository, snapshot, inference_id, etc.).
Search & fetch documents
- Quick document lookup by id: call
getwithindexandid. - Freeform query: call
searchwithindex(or omit for all) and a query DSL inbody.query. If you need multiple queries in one request usemsearch. - Count results:
countaccepts a query body orqstring. - Paging and long-lived cursors: prefer
open-point-in-time(PIT) thensearchwithpit_idfor consistent paging; close withclose-point-in-time.
Index, update, delete, bulk ingest
- Index a single document:
index(orcreateif you require create-only semantics) withindex,id, andbody. - Update partial document:
updatewithindex,id, andbody.docorscript. - Delete document:
deletewithindexandid. - High throughput ingest:
bulkwithbodyas an array of action lines. Checkerrorsand theitemsarray in the response for per-operation failures. Usepipelineto route through an ingest pipeline.
Bulk and indexing gotcha: bulk responses don’t throw for partial failures — always inspect errors and the items list.
Reindex / transform / update-by-query
- Reindex to copy data:
reindexwithbody.sourceandbody.dest. For large jobs, usewait_for_completion=falseto run async, inspecttaskin response, then use tasks APIs to monitor orreindex-rethrottleto change speed. - Update or delete by query:
update-by-query/delete-by-query; these acceptwait_for_completionand producetaskif async. Use*_rethrottleendpoints to adjust throughput.
Snapshots and restore
- Create repository:
snapshot-create-repository(must exist before snapshots). - Create snapshot:
snapshot-createwithrepository+snapshotname. Usewait_for_completionwhen you want synchronous completion. - List snapshots:
snapshot-getandsnapshot-status. - Restore:
snapshot-restorewithrepository+snapshot, optionallyindices,rename_pattern,rename_replacement, andinclude_global_state(see gotchas).
Snapshot gotcha: include_global_state=true will restore cluster-level objects (templates, ingest pipelines, ILM) and can overwrite cluster persistent settings—do not set it unless you intend to restore cluster state.
Async searches, EQL, ES|QL, and SQL
- Async search (search saved on cluster): use
async-search-submit(or client-sidesearchwithwait_for_completion_timeoutandkeep_on_completion) which returns anid. Poll withasync-search-getor checkasync-search-status; delete withasync-search-deletewhen finished. - EQL async:
eql-search(oreql-searchwithwait_for_completion_timeout) returns similar asyncid; useeql-get,eql-get-status,eql-delete. - ES|QL async:
esql-async-queryreturns an ID; retrieve withesql-async-query-getand stop withesql-async-query-stop. - SQL:
sql-querysupports sync or becomes async depending onwait_for_completion_timeout;sql-translateconverts SQL to DSL;sql-get-asyncandsql-delete-asyncmanage async SQL.
Async gotchas: many async endpoints accept keep_alive (how long results are stored) and wait_for_completion_timeout (how long to wait synchronously). If you get an id back, poll the appropriate GET/status endpoint to obtain results.
Ingest pipelines and simulation
- Create pipeline:
ingest-put-pipelinewithidandbody.processors. - Test pipeline:
ingest-simulatewithdocsand optionalpipelineorpipeline_substitutions.
Index template lifecycle
- Create component templates first if composing templates; then
indices-put-index-templatecomposes component templates into index template. If you need to preview template application, useindices-simulate-index-template/indices-simulate-templateorindices-createwithsettings/mappingsexplicitly.
Security, roles, and users (privileged operations)
- Manage security objects via
security-*endpoints (security-put-user,security-put-role,security-get-user, etc.). These APIs require appropriate privileges; many agent tasks in multi-tenant environments will not have rights to call them.
Inference and ML workflows
- Inference endpoints: create with
inference-put(or provider-specificinference-put-<provider>) using aninference_id, then invoke inference withinference-inference,inference-embedding,inference-text-embedding,inference-completion, or streaming variants. To list endpoints useinference-get. - Trained models: create with
ml-put-trained-modeland start deployment withml-start-trained-model-deployment; callml-infer-trained-modelto run inference directly.
ML gotchas: model deployment has number_of_allocations, queue_capacity, and wait_for semantics; deployments may be long-running and you must check ml-get-trained-models-stats or ml-start-trained-model-deployment response assignment details.
Transforms and rollups
- Create and manage transforms with
transform-put-transform, start/stop withtransform-start-transform/transform-stop-transform, and preview withtransform-preview-transform. - Rollups: create jobs with
rollup-put-job, start/stop viarollup-start-job/rollup-stop-job, and query rolled-up data withrollup-rollup-search.
Gotchas and non-obvious behaviors
-
Wildcards and missing indices: many index APIs accept
expand_wildcards,allow_no_indices, andignore_unavailable. If you expect wildcard patterns that might match nothing, supplyallow_no_indices=trueor the call may return 404. Conversely, some APIs default to strict behavior—verify theallow_no_match/allow_no_indicesbehavior for the specific operation. -
require_aliasandrequire_data_stream: write APIs (bulk,index,create) accept flags forcing target to be an alias or data stream. If your target is a data stream, setrequire_data_stream=trueotherwise the request fails. -
Long-running ops: many resource-intensive operations default to synchronous behavior unless you set
wait_for_completion=false. When they returntaskortask_id, use the tasks endpoints to inspect progress and*_rethrottleto adjust throughput. -
Templates vs existing indices: updating templates does not retroactively change existing indices. To apply mapping/setting changes you may need to create a new index and reindex or use composable templates and rollover workflows.
-
Bulk behavior:
bulkaccepts a mix of index/update/delete actions. The response is per-item;errors=truemeans at least one item failed. Retry only the failed items; inspect each item’s response. -
Snapshot restore cluster state:
include_global_state=truerestores cluster-level objects (templates/pipelines/ILM). This can overwrite cluster settings and templates—do not set unless intended. -
Index mappings and breaking changes: some mapping changes are non-dynamic and require closing an index and re-creating it (or using reindex into a new index). Use
indices-put-mappingfor dynamic updates; otherwise create a new index with desired mappings and reindex. -
Scroll vs PIT:
scrolluses scroll IDs and requires explicitclear-scroll. PIT offers a simpler, stateless paging pattern (open-point-in-time, search withpit_id) and must be closed withclose-point-in-time. -
Ingest pipelines and versioning: pipelines include
versionand are stored cluster-wide. When testing, useingest-simulateto validate behavior before indexing. -
Async search lifetime:
keep_alivecontrols how long the async search and results are retained. If you poll after the TTL, the id is gone.
Practical checklist for the most common user requests
-
Run a search: 1) ensure index name via
indices-getif needed; 2) callsearchwithindexandbody.query; 3) if the query is long-running, supplywait_for_completion_timeoutandkeep_on_completionto persist results. -
Index / bulk ingest: 1) if pipeline required, ensure pipeline exists (
ingest-get-pipeline); 2) callbulkwith action lines; 3) checkerrorsand retry failed items. -
Create an index from template: 1) create component templates if using
composed_of; 2) callindices-put-index-template; 3) create index (indices-create) or rely on rollover/data stream creation. -
Take a snapshot: 1) verify/create repository (
snapshot-create-repository); 2) callsnapshot-createwithrepository+snapshot; 3) usewait_for_completion=trueif you need completion before continuing. -
Restore a snapshot safely: 1) review snapshot contents (
snapshot-get); 2) if you must not alter cluster state, setinclude_global_state=false; 3) userename_pattern/rename_replacementto avoid name collisions. -
Start a heavy job (reindex/update-by-query): 1) call with
wait_for_completion=falseto gettask; 2) poll withtasks-getor use the returnedtaskto check progress; 3) adjust speed with*-rethrottleif supported.
When to inspect more metadata
- If a write appears missing, check index settings/mappings via
indices-getand the cluster health/shard allocation viacluster-healthandcat-shards/cat-allocation. - When debugging ingest pipeline behavior, run
ingest-simulateand inspectdocsresults for per-processor output.
Final note
Elasticsearch exposes many specialized APIs, but most user-facing tasks reduce to a few patterns: identify the index/data stream or resource id, call the specific create/update/start API, and for long-running actions choose sync (wait_for_completion) or async (capture task or id and poll the corresponding status endpoint). When in doubt about an ID, list the parent resource (indices, snapshots, transforms, jobs, models, connectors, inference endpoints) and use that canonical value in subsequent calls.