> For the complete documentation index, see [llms.txt](https://docs.envector.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.envector.io/1.5.x/api-reference/kms.md).

# KMSClient

## module `kms.client`

gRPC client for enVector Key Management Services.

Wraps the managed KMS gateway behind a single `KMSClient` facade. The gRPC channel is created lazily on first use and can be closed via `close()`.

### class `KMSClient`

```python
class KMSClient()
```

Client for the managed enVector KMS gateway.

All gRPC services are accessed through a single gateway address.

**ARGUMENTS**

* `address` (`str`): `host:port` of the KMS API Gateway (gRPC).
* `secure` (`bool`, optional): Use TLS channels. Defaults to `False`.

***

#### `generate_key()`

```python
def generate_key(key_id: str,
                 metadata_encryption: Optional[bool] = None) -> Dict[str, object]
```

Generate the KMS-managed key bundle for `key_id`.

This issues the managed `GenerateKey` RPC through `KeyManagerService`.

**ARGUMENTS**

* `key_id` (`str`): Client-specified key identifier.
* `metadata_encryption` (`bool`, optional): Whether metadata encryption should be enabled for the generated key bundle. If omitted, the server default is used.

**RETURNS**

`dict`: `{"key_id": str, "version": int, "status": str}`

***

#### `get_key_status()`

```python
def get_key_status(key_id: str) -> Dict[str, object]
```

Poll the status of an async key generation job.

**ARGUMENTS**

* `key_id` (`str`): Key ID returned by `generate_key`.

**RETURNS**

`dict`: `{"key_id": str, "status": str}`

***

#### `get_key_details()`

```python
def get_key_details(key_id: str) -> Dict[str, object]
```

Return version metadata for `key_id`.

The response includes per-version lifecycle state, key type, and audit metadata.

**ARGUMENTS**

* `key_id` (`str`): Identifier of the key.

**RETURNS**

`dict`: `{"key_id": str, "versions": list[dict]}`

Each `versions` entry contains:

* `version` (`int`)
* `state` (`str`)
* `key_type` (`str`)
* `created_at` (`str`)
* `updated_at` (`str`)
* `actor` (`str`)

***

#### `wait_for_key()`

```python
def wait_for_key(key_id: str,
                 timeout: float = 120,
                 poll_interval: float = 1.0) -> Dict[str, object]
```

Poll `get_key_status` until the key becomes ready, fails, or times out.

**ARGUMENTS**

* `key_id` (`str`): Key ID to poll.
* `timeout` (`float`): Maximum seconds to wait. Defaults to `120`.
* `poll_interval` (`float`): Seconds between polls. Defaults to `1.0`.

**RAISES**

* `TimeoutError`: If the key does not reach a terminal state within `timeout`.
* `KeyManagementError`: If key generation reaches a failed state.

**RETURNS**

`dict`: Final status dict from `get_key_status`.

***

#### `download_enc_key()`

```python
def download_enc_key(key_id: str) -> bytes
```

Download the raw wrapped EncKey for `key_id` via KMS gRPC.

The client reassembles the server-streamed chunks into a single `bytes` payload.

**ARGUMENTS**

* `key_id` (`str`): Key ID.

**RETURNS**

`bytes`: Raw EncKey binary data.

***

#### `download_eval_key()`

```python
def download_eval_key(key_id: str) -> bytes
```

Download the raw wrapped EvalKey for `key_id` via KMS gRPC.

The client reassembles the server-streamed chunks into a single `bytes` payload.

**ARGUMENTS**

* `key_id` (`str`): Key ID.

**RETURNS**

`bytes`: Raw EvalKey binary data.

***

#### `encrypt_metadata()`

```python
def encrypt_metadata(key_id: str,
                     plaintext_metadata: List[str]) -> List[bytes]
```

Encrypt plaintext metadata strings via KMS.

The metadata key remains inside KMS. Clients send plaintext and receive ciphertext bytes.

**ARGUMENTS**

* `key_id` (`str`): Metadata-enabled key identifier.
* `plaintext_metadata` (`list[str]`): Plaintext strings to encrypt.

**RETURNS**

`list[bytes]`: Encrypted metadata payloads.

***

#### `decrypt_metadata()`

```python
def decrypt_metadata(key_id: str,
                     encrypted_metadata: List[bytes]) -> List[str]
```

Decrypt metadata ciphertexts via KMS.

The metadata key remains inside KMS. Clients send ciphertext and receive plaintext strings.

**ARGUMENTS**

* `key_id` (`str`): Metadata-enabled key identifier.
* `encrypted_metadata` (`list[bytes]`): Ciphertexts produced by `encrypt_metadata`.

**RETURNS**

`list[str]`: Decrypted plaintext strings.

***

#### `topk()`

```python
def topk(key_id: str,
         encrypted_scores: list,
         k: int,
         score_threshold: Optional[float] = None,
         shard_indices: Optional[List[int]] = None) -> List["kms_msg_pb2.TopKResult"]
```

Decrypt encrypted scores via KMS and return ranked top-k results.

`shard_indices` can be provided to restrict evaluation to a subset of shards when the caller already knows the search partition.

**ARGUMENTS**

* `key_id` (`str`): Key ID used for decryption lookup.
* `encrypted_scores` (`list`): List of encrypted score protobuf messages, typically `type_pb2.EVCiphertext`.
* `k` (`int`): Number of top results to return.
* `score_threshold` (`float`, optional): Minimum score filter.
* `shard_indices` (`list[int]`, optional): Restrict evaluation to specific shard indices.

**RETURNS**

`list[TopKResult]`: Ranked results returned by the KMS `TopK` RPC.

***

#### `transition_state()`

```python
def transition_state(key_id: str,
                     *,
                     version: int | None = None,
                     new_state: int,
                     reason: str) -> bool
```

Transition the latest key version to a new lifecycle state.

`version` is reserved for future per-version targeting and is not currently supported.

**ARGUMENTS**

* `key_id` (`str`): Identifier of the key.
* `version` (`int | None`, optional): Reserved for future use. Passing a non-`None` value raises `NotImplementedError`.
* `new_state` (`int`): `kms_msg_pb2.KeyState` enum value.
* `reason` (`str`): Mandatory audit reason.

**RAISES**

* `NotImplementedError`: If `version` is specified.

**RETURNS**

`bool`: `True` when the transition request succeeds.

***

#### `delete_key()`

```python
def delete_key(key_id: str, reason: str) -> bool
```

Schedule a key for deletion via the managed gateway.

**ARGUMENTS**

* `key_id` (`str`): Identifier of the key.
* `reason` (`str`): Mandatory audit reason.

**RETURNS**

`bool`: `True` when the delete request succeeds.

***

#### `health_check_keygen()`

```python
def health_check_keygen() -> bool
```

Health check for `KeyManagerService`.

**RETURNS**

`bool`: `True` if the service is healthy, `False` otherwise.

***

#### `health_check_topk()`

```python
def health_check_topk() -> bool
```

Health check for `TopKService`.

**RETURNS**

`bool`: `True` if the service is healthy, `False` otherwise.

***

#### `close()`

```python
def close()
```

Close the gRPC channel and clear cached stubs.

***

#### `__enter__()`

```python
def __enter__()
```

Enter the context manager and return the client instance.

**RETURNS**

`KMSClient`: The current client instance.

***

#### `__exit__()`

```python
def __exit__(*exc)
```

Exit the context manager and close the client connection.

**RETURNS**

`bool`: `False`, so any exception is propagated to the caller.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.envector.io/1.5.x/api-reference/kms.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
