# OpenSearch compatibility

WarpSearch answers the OpenSearch REST API at `https://api.warpsearch.io/compat/opensearch`. It serves the same routes and the same query translation as the [Elasticsearch endpoint](compat-elasticsearch.md), but it presents itself as OpenSearch, so clients and tools that check which product they are talking to behave correctly.

Read the Elasticsearch page first for endpoints, the query and aggregation tables, mappings, write semantics and behavior differences. Everything there applies here. This page covers only what differs.

## What changes on the OpenSearch endpoint

| | Elasticsearch endpoint | OpenSearch endpoint |
|---|---|---|
| `GET /` | Version 8.11.0, `X-Elastic-Product` header | `distribution: opensearch`, version 2.19.0, OpenSearch tagline, no `X-Elastic-Product` header |
| Caller identity | `_security/_authenticate` | `_plugins/_security/authinfo` (and `_opendistro/_security/authinfo`); `_security/_authenticate` answers too |
| Index setting `index.knn: true` | Not applicable | Accepted without a warning |
| Settings `index.knn.*` | Not applicable | Accepted with a warning, no effect |

The forms that exist in only one product are accepted on either base URL. You can send an OpenSearch `knn` query to the Elasticsearch endpoint, or an Elasticsearch top-level `knn` section to the OpenSearch endpoint. Use the OpenSearch base URL when your client or tool branches on the product.

## Connect

Create an API key in the [management console](/console/). Send it as `Authorization: Bearer`, `Authorization: ApiKey` or `X-API-Key`.

> **Not supported:** HTTP Basic authentication with a console API key as the password. `opensearch-py`'s `http_auth` tuple sends Basic credentials, so send a header instead.

```python
from opensearchpy import OpenSearch

client = OpenSearch(
    hosts=[{"host": "api.warpsearch.io", "port": 443, "url_prefix": "compat/opensearch"}],
    use_ssl=True,
    headers={"Authorization": "Bearer ws_live_..."},
)

client.search(index="books", body={"query": {"match": {"title": "dune"}}})
```

curl:

```bash
curl -s https://api.warpsearch.io/compat/opensearch/books/_search \
  -H "Authorization: Bearer ws_live_..." \
  -H "Content-Type: application/json" \
  -d '{"query": {"match": {"title": "dune"}}}'
```

## k-NN search

Create an index with a `knn_vector` field and `index.knn: true`:

```json
PUT /products
{
  "settings": {"index": {"knn": true}},
  "mappings": {
    "properties": {
      "title": {"type": "text"},
      "embedding": {
        "type": "knn_vector",
        "dimension": 384,
        "method": {"name": "hnsw", "space_type": "cosinesimil"}
      }
    }
  }
}
```

Query it with the OpenSearch `knn` query:

```json
{
  "size": 10,
  "query": {
    "knn": {
      "embedding": {
        "vector": [0.12, -0.03, 0.88],
        "k": 10,
        "filter": {"term": {"in_stock": "yes"}},
        "method_parameters": {"ef_search": 100, "nprobes": 8}
      }
    }
  }
}
```

| OpenSearch parameter | Behavior |
|---|---|
| `k` | Bounded by your plan's result window |
| `filter` | Applied inside the vector search, so it narrows candidates before ranking |
| `method_parameters.ef_search` | Sizes the candidate pool that is rescored at full precision. At most 10000, at least `k` |
| `method_parameters.nprobes` | Search effort on approximate indexes |
| `rescore.oversample_factor` | Widens the rescoring pool |
| `dimension` | Up to 8192 |
| `ivf` and `exact` (extensions) | Tune recall, or force a full scan for ground truth |

A `knn_vector` mapping with `method.name` of `hnsw` or `ivf` asks for an approximate index. WarpSearch builds it when you call `_refresh` or `_forcemerge`; until then every search scans exactly. Other build parameters (`m`, `ef_construction`, `engine`, `nlist`, encoders, `mode`, `compression_level`) are accepted and reported as warnings.

A `knn` query combined with other scoring clauses in a `bool`, several `knn` clauses, or a `boost` produce hybrid search. A document matches if any clause does, and its score is the sum of the clause scores times their boosts. kNN scores are WarpSearch similarity scores, not OpenSearch's. See [Vector search](vector-search.md) and [Hybrid search](hybrid-search.md).

> **Not supported:** radial search (`max_distance` or `min_score` without `k`), `neural` and `neural_sparse` queries, the `hybrid` query with a search pipeline, binary `knn_vector` data types, and nested `knn_vector` fields. Requests that use them fail with `400` and `unsupported_feature`. Compute embeddings in your application and send the vector.

## Ingest tools

Tools that write to OpenSearch can write to WarpSearch through `_bulk`. Set the output's host to `https://api.warpsearch.io/compat/opensearch`, authenticate with a header carrying your API key, and use an index name that matches a collection.

| Tool | Notes |
|---|---|
| Data Prepper | `opensearch` sink. Needs custom headers for authentication |
| Logstash | `opensearch` output plugin, or the `elasticsearch` output against the Elasticsearch endpoint |
| Fluent Bit | `opensearch` output |
| Vector, Filebeat, other shippers | Their Elasticsearch or OpenSearch sinks |

These tools make a few startup calls of their own before they send data, such as version, license or template probes. WarpSearch answers the version and root probes. It does not serve `_license`, `_xpack` or index template APIs, and we have not verified every tool and version against that. Test your shipper with a small batch before you move production traffic, and check for `404` or `unsupported_feature` responses in its log. If a tool insists on installing an index template or an ingest pipeline, disable that step and create the collection yourself.

Remember the write rules from the Elasticsearch page. There is no dynamic mapping, so create the collection with a mapping first, or name fields with type suffixes. `create` overwrites. Partial updates are not supported.

## Grafana

Grafana's OpenSearch datasource works against the OpenSearch endpoint for logs and metrics panels. Choose the collection as the index and the time field you mapped. For query syntax see [Query languages](query-languages.md).

## Not supported

On both base URLs, these OpenSearch features fail with `unsupported_feature` or are not served:

> **Not supported:** the `neural`, `neural_sparse` and `hybrid` queries, search pipelines (a `search_pipeline` body key or URL parameter other than `_none`), the `template` and `common` queries, derived fields, PPL (`_plugins/_ppl`), the SQL plugin endpoint (`_plugins/_sql`), OpenSearch Dashboards, Index State Management, alerting, security plugin APIs other than caller identity, snapshots, cross-cluster search and ML Commons.

The rest of the gap list is the same as on the Elasticsearch endpoint: no scroll or `search_after`, no nested documents or joins, no scripts, no multi-index search, no update by query, and no highlighting. Several of these are in development, see [Roadmap and status](roadmap-and-status.md).

> **Coming soon:** highlighting, `boolean` and `ip` field types, range and flattened types, polygon geo queries and bounded total hits.

If you need SQL over your data, WarpSearch has its own SQL query language on the native API. See [Query languages](query-languages.md).
