--- type: docs title: "State management API reference" linkTitle: "State management API" description: "Detailed documentation on the state management API" weight: 400 --- ## Component file A Dapr `statestore.yaml` component file has the following structure: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: namespace: spec: type: state. version: v1 metadata: - name: value: - name: value: ``` | Setting | Description | | ------- | ----------- | | `metadata.name` | The name of the state store. | | `spec/metadata` | An open key value pair metadata that allows a binding to define connection properties. | ## Key scheme Dapr state stores are key/value stores. To ensure data compatibility, Dapr requires these data stores follow a fixed key scheme. For general states, the key format is: ``` || ``` For Actor states, the key format is: ``` |||||| ``` ## Save state This endpoint lets you save an array of state objects. ### HTTP Request ``` POST http://localhost:/v1.0/state/ ``` #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | The `metadata.name` field in the user-configured `statestore.yaml` component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. The optional request metadata is passed via URL query parameters. For example, ``` POST http://localhost:3500/v1.0/state/myStore?metadata.contentType=application/json ``` > All URL parameters are case-sensitive. > Since `||` is a reserved string it cannot be used in the `` > field. #### Request Body A JSON array of state objects. Each state object is comprised with the following fields: Field | Description ---- | ----------- `key` | State key `value` | State value, which can be any byte array `etag` | (optional) State ETag `metadata` | (optional) Additional key-value pairs to be passed to the state store `options` | (optional) State operation options; see [state operation options](#optional-behaviors) > **ETag format:** Dapr runtime treats ETags as opaque strings. The exact ETag format is defined by the corresponding data store. #### Metadata Metadata can be sent via query parameters in the request's URL. It must be prefixed with `metadata.`, as shown below. Parameter | Description --------- | ----------- `metadata.ttlInSeconds` | The number of seconds for the message to expire, as [described here]({{< ref state-store-ttl.md >}}) > **TTL:** Only certain state stores support the TTL option, according the [supported state stores]({{< ref supported-state-stores.md >}}). ### HTTP Response #### Response Codes Code | Description ---- | ----------- `204` | State saved `400` | State store is missing or misconfigured or malformed request `500` | Failed to save state #### Response Body None. ### Example ```shell curl -X POST http://localhost:3500/v1.0/state/starwars?metadata.contentType=application/json \ -H "Content-Type: application/json" \ -d '[ { "key": "weapon", "value": "DeathStar", "etag": "1234" }, { "key": "planet", "value": { "name": "Tatooine" } } ]' ``` ## Get state This endpoint lets you get the state for a specific key. ### HTTP Request ``` GET http://localhost:/v1.0/state// ``` #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | `metadata.name` field in the user-configured statestore.yaml component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. `key` | The key of the desired state `consistency` | (optional) Read consistency mode; see [state operation options](#optional-behaviors) `metadata` | (optional) Metadata as query parameters to the state store The optional request metadata is passed via URL query parameters. For example, ``` GET http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json ``` > Note, all URL parameters are case-sensitive. ### HTTP Response #### Response Codes Code | Description ---- | ----------- `200` | Get state successful `204` | Key is not found `400` | State store is missing or misconfigured `500` | Get state failed #### Response Headers Header | Description --------- | ----------- `ETag` | ETag of returned value #### Response Body JSON-encoded value ### Example ```shell curl http://localhost:3500/v1.0/state/starwars/planet?metadata.contentType=application/json ``` > The above command returns the state: ```json { "name": "Tatooine" } ``` To pass metadata as query parameter: ``` GET http://localhost:3500/v1.0/state/starwars/planet?metadata.partitionKey=mypartitionKey&metadata.contentType=application/json ``` ## Get bulk state This endpoint lets you get a list of values for a given list of keys. ### HTTP Request ``` POST/PUT http://localhost:/v1.0/state//bulk ``` #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | `metadata.name` field in the user-configured statestore.yaml component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. `metadata` | (optional) Metadata as query parameters to the state store The optional request metadata is passed via URL query parameters. For example, ``` POST/PUT http://localhost:3500/v1.0/state/myStore/bulk?metadata.partitionKey=mypartitionKey ``` > Note, all URL parameters are case-sensitive. ### HTTP Response #### Response Codes Code | Description ---- | ----------- `200` | Get state successful `400` | State store is missing or misconfigured `500` | Get bulk state failed #### Response Body An array of JSON-encoded values ### Example ```shell curl http://localhost:3500/v1.0/state/myRedisStore/bulk \ -H "Content-Type: application/json" \ -d '{ "keys": [ "key1", "key2" ], "parallelism": 10 }' ``` > The above command returns an array of key/value objects: ```json [ { "key": "key1", "value": "value1", "etag": "1" }, { "key": "key2", "value": "value2", "etag": "1" } ] ``` To pass metadata as query parameter: ``` POST http://localhost:3500/v1.0/state/myRedisStore/bulk?metadata.partitionKey=mypartitionKey ``` ## Delete state This endpoint lets you delete the state for a specific key. ### HTTP Request ``` DELETE http://localhost:/v1.0/state// ``` #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | `metadata.name` field in the user-configured statestore.yaml component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. `key` | The key of the desired state `concurrency` | (optional) Either *first-write* or *last-write*; see [state operation options](#optional-behaviors) `consistency` | (optional) Either *strong* or *eventual*; see [state operation options](#optional-behaviors) The optional request metadata is passed via URL query parameters. For example, ``` DELETE http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json ``` > Note, all URL parameters are case-sensitive. #### Request Headers Header | Description --------- | ----------- If-Match | (Optional) ETag associated with the key to be deleted ### HTTP Response #### Response Codes Code | Description ---- | ----------- `204` | Delete state successful `400` | State store is missing or misconfigured `500` | Delete state failed #### Response Body None. ### Example ```shell curl -X DELETE http://localhost:3500/v1.0/state/starwars/planet -H "If-Match: xxxxxxx" ``` ## Query state This endpoint lets you query the key/value state. {{% alert title="alpha" color="warning" %}} This API is in alpha stage. {{% /alert %}} ### HTTP Request ``` POST/PUT http://localhost:/v1.0-alpha1/state//query ``` #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | `metadata.name` field in the user-configured statestore.yaml component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. `metadata` | (optional) Metadata as query parameters to the state store The optional request metadata is passed via URL query parameters. For example, ``` POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json ``` > Note, all URL parameters are case-sensitive. #### Response Codes Code | Description ---- | ----------- `200` | State query successful `400` | State store is missing or misconfigured `500` | State query failed #### Response Body An array of JSON-encoded values ### Example ```shell curl -X POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json \ -H "Content-Type: application/json" \ -d '{ "filter": { "OR": [ { "EQ": { "person.org": "Dev Ops" } }, { "AND": [ { "EQ": { "person.org": "Finance" } }, { "IN": { "state": [ "CA", "WA" ] } } ] } ] }, "sort": [ { "key": "state", "order": "DESC" }, { "key": "person.id" } ], "page": { "limit": 3 } }' ``` > The above command returns an array of objects along with a token: ```json { "results": [ { "key": "1", "data": { "person": { "org": "Dev Ops", "id": 1036 }, "city": "Seattle", "state": "WA" }, "etag": "6f54ad94-dfb9-46f0-a371-e42d550adb7d" }, { "key": "4", "data": { "person": { "org": "Dev Ops", "id": 1042 }, "city": "Spokane", "state": "WA" }, "etag": "7415707b-82ce-44d0-bf15-6dc6305af3b1" }, { "key": "10", "data": { "person": { "org": "Dev Ops", "id": 1054 }, "city": "New York", "state": "NY" }, "etag": "26bbba88-9461-48d1-8a35-db07c374e5aa" } ], "token": "3" } ``` To pass metadata as query parameter: ``` POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.partitionKey=mypartitionKey ``` ## State transactions Persists the changes to the state store as a [transactional operation]({{< ref "state-management-overview.md#transactional-operations" >}}). > This API depends on a state store component that supports transactions. Refer to the [state store component spec]({{< ref "supported-state-stores.md" >}}) for a full, current list of state stores that support transactions. #### HTTP Request ``` POST/PUT http://localhost:/v1.0/state//transaction ``` #### HTTP Response Codes Code | Description ---- | ----------- `204` | Request successful `400` | State store is missing or misconfigured or malformed request `500` | Request failed #### URL Parameters Parameter | Description --------- | ----------- `daprPort` | The Dapr port `storename` | `metadata.name` field in the user-configured statestore.yaml component file. Refer to the [Dapr state store configuration structure](#component-file) mentioned above. The optional request metadata is passed via URL query parameters. For example, ``` POST http://localhost:3500/v1.0/state/myStore/transaction?metadata.contentType=application/json ``` > Note, all URL parameters are case-sensitive. #### Request Body Field | Description ---- | ----------- `operations` | A JSON array of state `operation` `metadata` | (optional) The `metadata` for the transaction that applies to all operations All transactional databases implement the following required operations: Operation | Description --------- | ----------- `upsert` | Adds or updates the value `delete` | Deletes the value Each operation has an associated `request` that is comprised of the following fields: Request | Description ---- | ----------- `key` | State key `value` | State value, which can be any byte array `etag` | (optional) State ETag `metadata` | (optional) Additional key-value pairs to be passed to the state store that apply for this operation `options` | (optional) State operation options; see [state operation options](#optional-behaviors) #### Examples The example below shows an `upsert` operation for `key1` and a `delete` operation for `key2`. This is applied to the partition named 'planet' in the state store. Both operations either succeed or fail in the transaction. ```shell curl -X POST http://localhost:3500/v1.0/state/starwars/transaction \ -H "Content-Type: application/json" \ -d '{ "operations": [ { "operation": "upsert", "request": { "key": "key1", "value": "myData" } }, { "operation": "delete", "request": { "key": "key2" } } ], "metadata": { "partitionKey": "planet" } }' ``` ## Configuring state store for actors Actors don't support multiple state stores and require a transactional state store to be used with Dapr. [View which services currently implement the transactional state store interface]({{< ref "supported-state-stores.md" >}}). Specify which state store to be used for actors with a `true` value for the property `actorStateStore` in the metadata section of the `statestore.yaml` component file. For example, the following components yaml will configure Redis to be used as the state store for Actors. ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore spec: type: state.redis version: v1 metadata: - name: redisHost value: - name: redisPassword value: "" - name: actorStateStore value: "true" ``` ## Optional behaviors ### Key scheme A Dapr-compatible state store shall use the following key scheme: * *\||\* key format for general states * *\||\||\||\* key format for Actor states. ### Concurrency Dapr uses Optimized Concurrency Control (OCC) with ETags. Dapr makes the following requirements optional on state stores: * A Dapr-compatible state store may support optimistic concurrency control using ETags. The store allows the update when an ETag: * Is associated with an *save* or *delete* request. * Matches the latest ETag in the database. * When ETag is missing in the write requests, the state store shall handle the requests in a *last-write-wins* fashion. This allows optimizations for high-throughput write scenarios, in which data contingency is low or has no negative effects. * A store shall *always* return ETags when returning states to callers. ### Consistency Dapr allows clients to attach a consistency hint to *get*, *set*, and *delete* operation. Dapr supports two consistency levels: **strong** and **eventual**. #### Eventual Consistency Dapr assumes data stores are eventually consistent by default. A state should: * For *read* requests, return data from any of the replicas. * For *write* requests, asynchronously replicate updates to configured quorum after acknowledging the update request. #### Strong Consistency When a strong consistency hint is attached, a state store should: * For *read* requests, return the most up-to-date data consistently across replicas. * For *write*/*delete* requests, synchronously replicate updated data to configured quorum before completing the write request. ### Example: Complete options request example The following is an example *set* request with a complete `options` definition: ```shell curl -X POST http://localhost:3500/v1.0/state/starwars \ -H "Content-Type: application/json" \ -d '[ { "key": "weapon", "value": "DeathStar", "etag": "xxxxx", "options": { "concurrency": "first-write", "consistency": "strong" } } ]' ``` ### Example: Working with ETags The following is an example walk-through of an ETag usage when *setting*/*deleting* an object in a compatible state store. This sample defines Redis as `statestore`. 1. Store an object in a state store: ```shell curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "1" } ]' ``` 1. Get the object to find the ETag set automatically by the state store: ```shell curl http://localhost:3500/v1.0/state/statestore/sampleData -v * Connected to localhost (127.0.0.1) port 3500 (#0) > GET /v1.0/state/statestore/sampleData HTTP/1.1 > Host: localhost:3500 > User-Agent: curl/7.64.1 > Accept: */* > < HTTP/1.1 200 OK < Server: fasthttp < Date: Sun, 14 Feb 2021 04:51:50 GMT < Content-Type: application/json < Content-Length: 3 < Etag: 1 < Traceparent: 00-3452582897d134dc9793a244025256b1-b58d8d773e4d661d-01 < * Connection #0 to host localhost left intact "1"* Closing connection 0 ``` The returned ETag above was 1. If you send a new request to update or delete the data with the wrong ETag, it will return an error. Omitting the ETag will allow the request. ```shell # Update curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "2", "etag": "2" } ]' {"errorCode":"ERR_STATE_SAVE","message":"failed saving state in state store statestore: possible etag mismatch. error from state store: ERR Error running script (call to f_83e03ec05d6a3b6fb48483accf5e594597b6058f): @user_script:1: user_script:1: failed to set key nodeapp||sampleData"} # Delete curl -X DELETE -H 'If-Match: 5' http://localhost:3500/v1.0/state/statestore/sampleData {"errorCode":"ERR_STATE_DELETE","message":"failed deleting state with key sampleData: possible etag mismatch. error from state store: ERR Error running script (call to f_9b5da7354cb61e2ca9faff50f6c43b81c73c0b94): @user_script:1: user_script:1: failed to delete node app||sampleData"} ``` 1. Update or delete the object by simply matching the ETag in either the request body (update) or the `If-Match` header (delete). When the state is updated, it receives a new ETag that future updates or deletes will need to use. ```shell # Update curl -X POST http://localhost:3500/v1.0/state/statestore \ -H "Content-Type: application/json" \ -d '[ { "key": "sampleData", "value": "2", "etag": "1" } ]' # Delete curl -X DELETE -H 'If-Match: 1' http://localhost:3500/v1.0/state/statestore/sampleData ``` ## Next Steps - [State management overview]({{< ref state-management-overview.md >}}) - [How-To: Save & get state]({{< ref howto-get-save-state.md >}})