Search API reference

Detailed documentation on the search API

Dapr provides an API to manage indexes and to index, retrieve, delete, and query documents in lexical (full-text) search engines. For an overview of concepts and features, see the search API overview.

All HTTP request and response bodies use the JSON mapping of the search protobuf definitions:

  • Field names are in lowerCamelCase.
  • bytes fields, such as document content, are base64-encoded strings.
  • Enum values are sent and returned as their names, for example INDEX_ACK_COMPLETED.
  • 64-bit integers, such as documentCount and totalHits, are returned as strings.
  • Durations, such as waitTimeout, are strings with an s suffix, for example "10s" or "1.5s".
  • Responses include fields that hold their default value, for example "documentCount": "0", "score": 0, or an empty failedItems array. Fields declared optional are omitted when unset, for example continuationToken on the last page and totalHits when the search store can’t supply one.
  • Unknown request fields are ignored.

Routes without a request body (get index, list indexes, and delete index) take component-specific metadata as metadata.<key>=<value> query parameters.

Create index

Creates an index in the search store.

POST http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component. See a list of all available search components.
indexThe name of the index to create

Request body

FieldDescription
metadataComponent-specific index settings, such as attributes to declare as filterable or sortable. Optional

HTTP response codes

CodeDescription
200Index created
400Malformed request
404Search store not found
409Index already exists. Settings of the existing index are not changed
500Search store not configured or request failed

Example

curl -X POST http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles \
  -H "Content-Type: application/json" \
  -d '{
        "metadata": {
          "filterableAttributes": "category,price",
          "sortableAttributes": "price"
        }
      }'

Get index

Gets information about an index.

GET http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index

Query parameters

ParameterDescription
metadata.<key>Component-specific request metadata. Optional

Response content

FieldDescription
indexThe name of the index
documentCountApproximate number of documents in the index. Search stores that can’t supply this value efficiently return 0
propertiesComponent-specific index properties

HTTP response codes

CodeDescription
200Index information returned
404Search store or index not found
500Search store not configured or request failed

Example

curl http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles
{
  "index": "articles",
  "documentCount": "3",
  "properties": {
    "filterableAttributes": "category,price",
    "primaryKey": "id",
    "sortableAttributes": "id,price"
  }
}

List indexes

Lists the indexes in the search store.

GET http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component

Query parameters

ParameterDescription
metadata.<key>Component-specific request metadata. Optional

Response content

FieldDescription
indexesThe names of the indexes in the search store

HTTP response codes

CodeDescription
200Indexes returned
404Search store not found
500Search store not configured or request failed

Example

curl http://localhost:3500/v1.0-alpha1/search/mysearch/indexes
{
  "indexes": ["articles", "products"]
}

Delete index

Deletes an index and all the documents in it.

DELETE http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index to delete

Query parameters

ParameterDescription
metadata.<key>Component-specific request metadata. Optional

HTTP response codes

CodeDescription
200Index deleted
404Search store or index not found
500Search store not configured or request failed

When a resiliency retry policy retries the delete and a later attempt finds that the index no longer exists, the delete succeeds, because an earlier attempt most likely deleted it. A NOT_FOUND on the first attempt is returned as is.

Example

curl -X DELETE http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles

Index documents

Indexes documents with a keyed upsert. A document with an ID that already exists in the index is replaced.

POST http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>/documents

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index

Request body

FieldDescription
documentsThe documents to index. Every document must have a non-empty id that is unique within the request. Required
optionsIndexing options that control when the request returns. Optional
metadataComponent-specific request metadata. Optional

Document

FieldDescription
idCaller-supplied document identifier, unique within the index. Required
contentBase64-encoded UTF-8 JSON object. Field-level request options (searchFields, returnFields, highlightFields, sort, and filter) address its top-level and dotted nested keys. A document whose content is not a JSON object is reported in failedItems with INVALID_ARGUMENT and is not sent to the search store
metadataOpaque string key/value pairs stored with the document and returned unchanged. Metadata is not indexed, not filterable, and not addressable by field-level request options. Optional

Indexing options

The same options apply to every write: index documents, delete documents, and the vector API’s upsert and delete operations.

FieldDescription
modeWhen the request returns. One of:
  • INDEXING_MODE_RETURN_ON_ACCEPTANCE: return after the search store durably accepts the write for background processing. No eventual result is exposed by the API.
  • INDEXING_MODE_WAIT_FOR_COMPLETION: wait for the final result, up to waitTimeout.
  • INDEXING_MODE_UNSPECIFIED (default): same as INDEXING_MODE_RETURN_ON_ACCEPTANCE.
waitTimeoutHow long to wait for the write to complete, for example "10s". Required and must be positive with INDEXING_MODE_WAIT_FOR_COMPLETION, and must not be set with any other mode. When the request has a deadline, waitTimeout must be shorter than the remaining time. When the store has a resiliency timeout policy, waitTimeout must also be shorter than that timeout by at least a tenth of it, and by no less than 100ms. For example, with a 10s policy timeout, waitTimeout can be at most 9s
onWaitTimeoutWhat happens when waitTimeout expires. Required with INDEXING_MODE_WAIT_FOR_COMPLETION, and must not be set with any other mode. One of:
  • INDEXING_WAIT_TIMEOUT_ACTION_CONTINUE_ASYNC: return INDEX_ACK_QUEUED and let the queued write continue. Rejected with INVALID_ARGUMENT by search stores that have no queued acknowledgement.
  • INDEXING_WAIT_TIMEOUT_ACTION_FAIL_REQUEST: fail the request with DEADLINE_EXCEEDED. A resiliency retry policy doesn’t retry the request, and the search store isn’t guaranteed to cancel the write.

Indexing options that break these rules are rejected before the write reaches the store, with INVALID_ARGUMENT, the ERR_SEARCH_INVALID_REQUEST error code (ERR_VECTOR_INVALID_REQUEST for the vector API), and a google.rpc.BadRequest field violation on options or options.wait_timeout.

Response content

FieldDescription
ackThe acknowledgement boundary the write reached. Always set on success. One of:
  • INDEX_ACK_QUEUED: the search store accepted the write for asynchronous processing. This does not indicate that any document has been indexed. Also returned when the search store reports an acknowledgement that Dapr doesn’t recognize.
  • INDEX_ACK_COMPLETED: the search store completed the write, and failedItems contains every item-specific failure.
failedItemsItem-specific failures known when the request returns. Each item has the document id and an error with a canonical gRPC status code (code), a message, and details

When no document is left to write, because the request has no documents or every document was rejected, the search store isn’t called and ack is INDEX_ACK_COMPLETED.

HTTP response codes

CodeDescription
200Request accepted. Check ack and failedItems for the outcome of each document
400Malformed request, empty or duplicate document ID, or invalid indexing options
404Search store or index not found
500Search store not configured or request failed
504waitTimeout expired with INDEXING_WAIT_TIMEOUT_ACTION_FAIL_REQUEST

Example

curl -X POST http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles/documents \
  -H "Content-Type: application/json" \
  -d '{
        "documents": [
          {
            "id": "doc-1",
            "content": "eyJ0aXRsZSI6IkdldHRpbmcgc3RhcnRlZCB3aXRoIERhcHIiLCJjYXRlZ29yeSI6Imd1aWRlIiwicHJpY2UiOjEwfQ==",
            "metadata": { "author": "alice" }
          },
          {
            "id": "doc-2",
            "content": "WyJub3QiLCAiYW4iLCAib2JqZWN0Il0="
          }
        ],
        "options": {
          "mode": "INDEXING_MODE_WAIT_FOR_COMPLETION",
          "waitTimeout": "10s",
          "onWaitTimeout": "INDEXING_WAIT_TIMEOUT_ACTION_FAIL_REQUEST"
        }
      }'

In this example, the content of doc-2 is a JSON array rather than an object, so it is rejected while doc-1 is indexed:

{
  "failedItems": [
    {
      "id": "doc-2",
      "error": {
        "code": 3,
        "message": "content must be a JSON object",
        "details": []
      }
    }
  ],
  "ack": "INDEX_ACK_COMPLETED"
}

Get documents

Gets documents by ID.

POST http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>/documents/get

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index

Request body

FieldDescription
idsThe IDs of the documents to get. Required
includeContentWhether to return document content. When false (default), only id and metadata are returned. Optional
metadataComponent-specific request metadata. Optional

Response content

FieldDescription
documentsThe found documents, in request order. IDs that don’t exist are omitted. When includeContent isn’t true, content is an empty string

HTTP response codes

CodeDescription
200Documents returned
400Malformed request
404Search store or index not found
500Search store not configured or request failed

Example

curl -X POST http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles/documents/get \
  -H "Content-Type: application/json" \
  -d '{
        "ids": ["doc-1", "doc-42"],
        "includeContent": true
      }'
{
  "documents": [
    {
      "id": "doc-1",
      "content": "eyJjYXRlZ29yeSI6Imd1aWRlIiwicHJpY2UiOjEwLCJ0aXRsZSI6IkdldHRpbmcgc3RhcnRlZCB3aXRoIERhcHIifQ==",
      "metadata": { "author": "alice" }
    }
  ]
}

Delete documents

Deletes documents by ID. Deleting is a write and shares the acknowledgement model of index documents. IDs that don’t exist are not an error, and deletions never report failed items.

POST http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>/documents/delete

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index

Request body

FieldDescription
idsThe IDs of the documents to delete. Required
optionsIndexing options that control when the request returns. Optional
metadataComponent-specific request metadata. Optional

Response content

FieldDescription
ackINDEX_ACK_QUEUED or INDEX_ACK_COMPLETED, with the same meaning as for index documents. Always set on success

HTTP response codes

CodeDescription
200Deletion accepted or completed
400Malformed request or invalid indexing options
404Search store or index not found
500Search store not configured or request failed
504waitTimeout expired with INDEXING_WAIT_TIMEOUT_ACTION_FAIL_REQUEST

Example

curl -X POST http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles/documents/delete \
  -H "Content-Type: application/json" \
  -d '{
        "ids": ["doc-1", "doc-2"]
      }'
{
  "ack": "INDEX_ACK_QUEUED"
}

Queries an index.

POST http://localhost:<daprPort>/v1.0-alpha1/search/<storeName>/indexes/<index>/query

URL parameters

ParameterDescription
daprPortThe Dapr port
storeNameThe name of the search component
indexThe name of the index

Request body

FieldDescription
queryThe search query. When omitted, every document in the index matches. Optional
metadataComponent-specific request metadata. Optional

Search query

FieldDescription
textA full-text query. Set at most one of text and native
nativeA provider-native query as a JSON object, passed to the search store. See the component reference for the supported format. Set at most one of text and native
filterA filter written in the portable filter language. Optional
topKThe maximum number of hits to return in this page. When 0 or omitted, the component default is used. Optional
continuationTokenThe token returned by the previous page. Omitted for the first page. Optional
searchFieldsRestricts the full-text query to these content fields. Optional
returnFieldsReturns only these content fields in each hit. Optional
includeContentWhether to return document content in each hit. When false (default) and returnFields is empty, only id and metadata are returned. Optional
sortSort clauses, applied in order. Each clause has a field and an order of SORT_ORDER_ASC or SORT_ORDER_DESC. Optional
highlightFieldsContent fields for which to return highlighted fragments. Optional

A query that sets neither text nor native matches every document in the index, subject to filter. All query fields go inside query; because unknown fields are ignored, a field such as text placed at the top level of the request body has no effect.

Filter language

Filters are JSON objects that search components translate into their native query language. Field paths address keys of the document content and use dotted notation for nested keys, for example customer.region. A field set directly to a value is an equality match, and multiple conditions in the same object are combined with a logical AND.

TypeOperators
Comparison$eq, $ne, $gt, $gte, $lt, $lte
Set$in, $nin
Existence$exists (boolean)
Logical$and, $or, $not
{
  "$and": [
    { "category": { "$in": ["guide", "reference"] } },
    { "price": { "$gte": 10, "$lt": 50 } },
    { "$not": { "author.name": "bob" } }
  ]
}

Response content

FieldDescription
hitsThe matching documents. Each hit has a document, a score, and highlights
hits[].documentThe matching document. content is included when includeContent is true or returnFields is set, and is an empty string otherwise
hits[].scoreUnnormalised, provider-specific relevance score. Higher values indicate a more relevant match
hits[].highlightsHighlighted fragments, keyed by field name
totalHitsBest-effort total number of matching documents. Omitted when the search store can’t supply one
totalHitsRelationThe accuracy of totalHits: TOTAL_HITS_RELATION_EXACT, TOTAL_HITS_RELATION_LOWER_BOUND, or TOTAL_HITS_RELATION_ESTIMATE. TOTAL_HITS_RELATION_UNSPECIFIED when totalHits is omitted
continuationTokenAn opaque token to get the next page. Omitted when there are no more results

A continuation token is bound to the query that produced it. To get the next page, send the same query with query.continuationToken set to the token; changing the query, filter, sort, or field options returns INVALID_ARGUMENT. If the search store’s cursor behind the token has expired, the request fails with FAILED_PRECONDITION and the SEARCH_CONTINUATION_EXPIRED error reason.

HTTP response codes

CodeDescription
200Search results returned
400Malformed request, invalid filter, invalid continuation token, or expired continuation token
404Search store or index not found
500Search store not configured or request failed

Example

curl -X POST http://localhost:3500/v1.0-alpha1/search/mysearch/indexes/articles/query \
  -H "Content-Type: application/json" \
  -d '{
        "query": {
          "text": "dapr",
          "filter": { "category": "guide" },
          "sort": [ { "field": "price", "order": "SORT_ORDER_ASC" } ],
          "highlightFields": ["title"],
          "includeContent": true,
          "topK": 10
        }
      }'
{
  "hits": [
    {
      "document": {
        "id": "doc-1",
        "content": "eyJjYXRlZ29yeSI6Imd1aWRlIiwicHJpY2UiOjEwLCJ0aXRsZSI6IkdldHRpbmcgc3RhcnRlZCB3aXRoIERhcHIifQ==",
        "metadata": { "author": "alice" }
      },
      "score": 0.9,
      "highlights": {
        "title": "Getting started with <em>Dapr</em>"
      }
    }
  ],
  "totalHits": "1",
  "totalHitsRelation": "TOTAL_HITS_RELATION_ESTIMATE"
}

Errors

Errors the Dapr runtime detects itself, such as a missing search store or an invalid request, are returned in the standard Dapr error format with the following error codes:

Error codeHTTP statusgRPC codeDescription
ERR_SEARCH_STORE_NOT_FOUND404NOT_FOUNDThe named search store doesn’t exist
ERR_SEARCH_STORE_NOT_CONFIGURED500FAILED_PRECONDITIONNo search store is configured
ERR_SEARCH_INVALID_REQUEST400INVALID_ARGUMENTThe request failed validation, for example an empty or duplicate document ID or invalid indexing options. A google.rpc.BadRequest detail names the offending field, such as documents.id, options, or options.wait_timeout
ERR_MALFORMED_REQUEST400N/AThe HTTP request body is not valid JSON

Errors returned by the search store, such as a missing index, are passed through with their canonical gRPC status code and details. Over HTTP, the response body uses the canonical code name as errorCode, carries the status details in details, and the HTTP status is mapped from the code:

gRPC codeHTTP status
INVALID_ARGUMENT, FAILED_PRECONDITION, OUT_OF_RANGE400
UNAUTHENTICATED401
PERMISSION_DENIED403
NOT_FOUND404
CANCELLED408
ALREADY_EXISTS, ABORTED409
RESOURCE_EXHAUSTED429
UNKNOWN, INTERNAL, DATA_LOSS500
UNIMPLEMENTED501
UNAVAILABLE503
DEADLINE_EXCEEDED504
{
  "errorCode": "ALREADY_EXISTS",
  "message": "meilisearch index \"articles\" already exists"
}

An error with details, such as an expired continuation token:

{
  "errorCode": "FAILED_PRECONDITION",
  "message": "...",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
      "reason": "SEARCH_CONTINUATION_EXPIRED",
      "domain": "dapr.io"
    }
  ]
}

A search store error that carries no gRPC status is reported as INTERNAL.

Resiliency

Search store calls run under the store’s resiliency policy:

  • Retry policies can match the search store’s canonical gRPC code with matching.gRPCStatusCodes.
  • A policy timeout is returned as DEADLINE_EXCEEDED, a cancelled request as CANCELLED, and an open circuit breaker as UNAVAILABLE.
  • ALREADY_EXISTS on a retried create index is returned unchanged, because the index may belong to another caller. NOT_FOUND on a retried delete index is treated as success.
  • A write whose INDEXING_WAIT_TIMEOUT_ACTION_FAIL_REQUEST wait expired isn’t retried.

Error reasons

Some errors carry a google.rpc.ErrorInfo detail in the dapr.io domain with one of the following reasons:

ReasonCodeDescription
SEARCH_CONTINUATION_EXPIREDFAILED_PRECONDITIONThe search store cursor referenced by a continuation token has expired. Restart the query from the first page
INDEXING_OUTCOME_UNKNOWNVariesThe search store reported a batch-level failure but could not establish which items were applied. Retry the request; keyed upserts and deletes are idempotent

gRPC API

The search API is also available over gRPC through the Dapr service in the Dapr runtime protos:

RPCDescription
CreateIndexAlpha1Create an index
GetIndexAlpha1Get an index
ListIndexesAlpha1List indexes
DeleteIndexAlpha1Delete an index
IndexDocumentsAlpha1Index documents
GetDocumentsAlpha1Get documents
DeleteDocumentsAlpha1Delete documents
SearchAlpha1Search an index

Over gRPC, storeName and index are fields of the request message and content is sent as raw bytes.

Next steps

Last modified October 20, 2026: update docs (b07992cd2)