---
layout: docs
page_title: KV - Secrets Engines
description: The KV secrets engine can store arbitrary secrets.
---

# KV secrets engine

The `kv` secrets engine is a generic key-value store used to store arbitrary
secrets within the configured physical storage for Vault. This secrets engine
can run in one of two modes; store a single value for a key, or store a number
of versions for each key and maintain the record of them.

## KV version 1

When running the `kv` secrets engine non-versioned, it stores the most recently
written value for a key. Any update will overwrite the original value and not
recoverable. The benefits of non-versioned `kv` is a reduced storage size for
each key since no additional metadata or history is stored. Additionally, it
gives better runtime performance because the requests require fewer storage
calls and no locking.

Refer to the [KV version 1 Docs](/vault/docs/secrets/kv/kv-v1) for more
information.

## KV version 2

When running v2 of the `kv` secrets engine, a key can retain a configurable
number of versions. The default is 10 versions. The older versions' metadata and
data can be retrieved. Additionally, it provides check-and-set operations to
prevent overwriting data unintentionally.

When a version is deleted, the underlying data is not removed, rather it is
marked as deleted. Deleted versions can be undeleted. To permanently remove a
version's data, use the `vault kv destroy` command or the API endpoint. You can
delete all versions and metadata for a key by deleting the metadata using the
`vault kv metadata delete` command or the API endpoint with DELETE verb. You can
restrict who has permissions to soft delete, undelete, or fully remove data with
[Vault policies](/vault/docs/concepts/policies).

Refer to the [KV version 2 Docs](/vault/docs/secrets/kv/kv-v2) for more
information.


## Version comparison

Regardless of its version, you use the [`vault kv`](/vault/docs/commands/kv)
command to interact with KV secrets engine. However, the API endpoint are
different. You must be aware of those differences to write policies as intended.

The following table lists the `vault kv` sub-commands and their respective API
endpoints assuming the KV secrets engine is enabled at `secret/`.


| Command           | KV v1 endpoint    | KV v2 endpoint                 |
| ----------------- | ----------------- | ------------------------------ |
| `vault kv get`    | secret/<key_path> | secret/**data**/<key_path>     |
| `vault kv put`    | secret/<key_path> | secret/**data**/<key_path>     |
| `vault kv list`   | secret/<key_path> | secret/**metadata**/<key_path> |
| `vault kv delete` | secret/<key_path> | secret/**data**/<key_path>     |

In addition, KV v2 has sub-commands to handle versioning of secrets.

| Command             | KV v2 endpoint                 |
| ------------------- | ------------------------------ |
| `vault kv patch`    | secret/**data**/<key_path>     |
| `vault kv rollback` | secret/**data**/<key_path>     |
| `vault kv undelete` | secret/**undelete**/<key_path> |
| `vault kv destroy`  | secret/**destroy**/<key_path>  |
| `vault kv metadata` | secret/**metadata**/<key_path> |


To reduce confusion, the CLI command outputs the secret path when you are
working with KV v2.

**Example:**

<CodeBlockConfig hideClipboard highlight="4">

```shell-session 
$ vault kv put secret/web-app api-token="WEOIRJ13895130WENJWEFN"

=== Secret Path ===
secret/data/web-app

======= Metadata =======
Key                Value
---                -----
created_time       2024-07-02T00:34:58.074825Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1
```

</CodeBlockConfig>

You can use `-mount` flag if omitting `/data/` in the CLI command is confusing.

```shell-session
$ vault kv put -mount=secret web-app api-token="WEOIRJ13895130WENJWEFN"
```
