DocsReference
OpenSearch compatibility
Search implements a documented subset of the OpenSearch REST API. GET / reports opensearch 3.5.0 so that official clients connect. That describes the wire protocol, not full feature parity.
Explicit, not silentAn unsupported query, aggregation, parameter or API returns a clear error. Search never accepts a request and quietly ignores the parts that would change your results.
How this is tested: the official opensearch-py client runs end to end in CI, and a differential suite compares responses with a real OpenSearch 2.19.1 instance.
APIs
| Area | Endpoints | Notes |
|---|---|---|
| Indices | PUT GET HEAD DELETE /{index}, GET /{index}/_mapping, /{index}/_refresh | Mappings can only be set at creation. |
| Documents | PUT /{index}/_doc/{id} (incl. op_type=create), POST /{index}/_doc, GET HEAD DELETE /{index}/_doc/{id} | Real-time GET sees acknowledged writes before refresh. |
| Update | POST /{index}/_update/{id} | Partial merge, upsert, doc_as_upsert. No scripts. |
| Bulk | POST /_bulk, /{index}/_bulk | index, create, update, delete. |
| Search | /{index}/_search, /{index}/_count, /_msearch, /{index}/_msearch | msearch runs its items one after another, 64 by default. |
| Point in time | POST /{index}/_search/point_in_time, pit in the body, DELETE /_search/point_in_time[/_all] | Use with search_after for deep pagination. |
| Aliases | POST /_aliases, GET /_alias/{alias}, GET /{index}/_alias, PUT DELETE /{index}/_alias/{alias} | |
| Tasks | POST /_reindex, /{index}/_update_by_query, /{index}/_delete_by_query, GET /_tasks/{id}, POST /_tasks/{id}/_cancel | Durable and resumable. |
| Templates and streams | /_index_template/{name}, /_data_stream/{name}, POST /{alias}/_rollover | Thin template API. Rollover takes no conditions. Lifecycle is an engine-specific lifecycle block. |
| Security | /_plugins/_security/api/{internalusers,roles,rolesmapping}, /_plugins/_security/api/account | Other _plugins/_security paths return 400. |
| Health | GET /, GET /_cluster/health | A healthy single-region install reports yellow, as a single-node OpenSearch does. |
Queries
| Supported | Refused with an error |
|---|---|
match_all, match, term, terms, range, exists, bool, match_phrase, match_phrase_prefix, prefix, wildcard, regexp, fuzzy, multi_match (best_fields, most_fields, phrase, phrase_prefix). boost is accepted on all of them. |
query_string, simple_query_string, knn, neural, nested, ids, constant_score, dis_max, function_score, script, script_score, geo_*, span_*, more_like_this, percolate, and others. |
Search body options: from / size, sort (including _seq_no), _source includes and excludes, track_total_hits, search_after and pit. Use ?search_type=dfs_query_then_fetch for globally consistent scoring.
Aggregations
| Supported | Refused with an error |
|---|---|
min, max, sum, avg, value_count, terms. No sub-aggregations. |
date_histogram, histogram, cardinality, filter, filters, range, percentiles, stats, top_hits, composite, nested, pipeline aggregations, and others. |
Mappings and field types
Types: text, keyword, integer, long, float, double, boolean, date, dense_vector.
- Strict mappings. Every field must be declared. An unknown field or an incompatible type is rejected, and there is no dynamic mapping.
typeis the only mapping parameter.analyzer,index,storeand the rest are refused.- Arrays (other than
dense_vector) and nested or dotted field paths are refused. - The analyzer is a simple lowercase tokenizer chain, not OpenSearch's
standardanalyzer, so relevance scores and some matches can differ.
Not supported
- Multi-index requests: wildcards, comma-separated lists and
_all. Each request targets exactly one index. _search/scroll: use point-in-time withsearch_afterinstead._cat,_mget,_settingsand per-index settings./_snapshot: snapshots are managed in the console. They are metadata-only and live in the same bucket, so they are not independent backups.- Highlighting, URI search (
?q=), and gzip request or response bodies. Official clients default to uncompressed. - Security features: document- and field-level security, OIDC/SAML and multi-tenancy.
- Scripting of any kind.
Engine-specific extensions
These endpoints have no OpenSearch equivalent and are documented as extensions.
| Endpoint | Purpose |
|---|---|
POST /{index}/_documents | Import plain text or Markdown with automatic chunking. Source IDs are immutable, so an identical retry resumes. |
POST /{index}/_semantic_search | Exact cosine retrieval with optional hybrid reciprocal-rank fusion. It scans 10,000 filtered documents by default (100,000 maximum), handles up to 4,096 dimensions and returns up to 1,000 hits. Over-budget requests fail explicitly. |
/{index}/_estimate | Returns a query's cost estimate without running it. |
/_security/apikey, /_security/sigv4 | Create and revoke API keys and SigV4 credentials. A secret is shown once. |
/_migration/… | Analyze, copy, cut over and roll back an index from OpenSearch. The source must be quiesced; there is no change-data capture. |
GET /_license | License state (see Licensing). |
Behaviour worth knowing
- Durability and visibility are separate. A write is acknowledged once it is in the write-ahead log in S3. Search sees it after a refresh, or after
?refresh=wait_for. - Queries over the cost budget are rejected with 429 rather than running up unbounded S3 reads.