> For the complete documentation index, see [llms.txt](https://vectis.liesware.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://vectis.liesware.com/keys.md).

# Keys

## List keys loaded in local memory

> Public endpoint. Lists keys currently loaded in this node's in-memory state. Decrypted lifecycle properties are not exposed here.

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"paths":{"/keys":{"get":{"tags":["Keys"],"summary":"List keys loaded in local memory","description":"Public endpoint. Lists keys currently loaded in this node's in-memory state. Decrypted lifecycle properties are not exposed here.","responses":{"200":{"description":"Loaded key list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListKeysOutput"}}}},"default":{"$ref":"#/components/responses/Error"}}}}},"components":{"schemas":{"ListKeysOutput":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"object","required":["kid","info"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"},"info":{"$ref":"#/components/schemas/TextField"}}}}}},"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}}},"responses":{"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}
```

## POST /keys

> Create operational key material

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"CreateKeysInput":{"type":"object","additionalProperties":false,"properties":{"tag":{"$ref":"#/components/schemas/AadSafeText"},"profile":{"$ref":"#/components/schemas/CryptoProfile"},"hash_algorithm":{"$ref":"#/components/schemas/HashAlgorithm"},"symmetric_algorithm":{"$ref":"#/components/schemas/SymmetricAlgorithm"},"eddsa_algorithm":{"$ref":"#/components/schemas/EdDsaAlgorithm"},"xecdh_algorithm":{"$ref":"#/components/schemas/XecdhAlgorithm"},"ml_dsa_variant":{"$ref":"#/components/schemas/MlDsaVariant"},"ml_kem_variant":{"$ref":"#/components/schemas/MlKemVariant"}},"description":"When VECTIS_CRYPTO_POLICY=profile-only, only tag and profile are accepted. Individual algorithm fields are accepted only when VECTIS_CRYPTO_POLICY=allow-overrides. Optional fields may be omitted, but explicit null values are rejected.\n"},"AadSafeText":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F;=]+$","description":"Text safe to embed in a key=value;... AAD string (no ';' or '=')."},"CryptoProfile":{"enum":["hybrid-performance-v1","hybrid-standard-v1","hybrid-high-assurance-v1","hybrid-long-term-v1"]},"HashAlgorithm":{"enum":["BLAKE2b(160)","BLAKE2b(224)","BLAKE2b(256)","BLAKE2b(384)","BLAKE2b(512)","SHA-224","SHA-256","SHA-384","SHA-512","SHA-512-256","SHA-3(224)","SHA-3(256)","SHA-3(384)","SHA-3(512)","Whirlpool"]},"SymmetricAlgorithm":{"enum":["ChaCha20Poly1305","AES-128/GCM","AES-192/GCM","AES-256/GCM"]},"EdDsaAlgorithm":{"enum":["Ed25519","Ed448"]},"XecdhAlgorithm":{"enum":["X25519","X448"]},"MlDsaVariant":{"enum":["ML-DSA-44","ML-DSA-65","ML-DSA-87"]},"MlKemVariant":{"enum":["ML-KEM-512","ML-KEM-768","ML-KEM-1024"]},"CreateKeysResponse":{"type":"object","required":["kid"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"}}},"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"}},"responses":{"RequestBodyTooLarge":{"description":"Request body exceeds the internal 2 MiB limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/keys":{"post":{"tags":["Keys"],"summary":"Create operational key material","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeysInput"}}}},"responses":{"200":{"description":"Created key KID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeysResponse"}}}},"413":{"$ref":"#/components/responses/RequestBodyTooLarge"},"default":{"$ref":"#/components/responses/Error"}}}}}}
```

## Refresh local key state from storage

> Administrative operation. Reloads and decrypts keys plus encrypted lifecycle properties from storage into this node's memory. Uses POST because it changes server memory state.

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"ListKeysPropertiesOutput":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"object","required":["kid","info","properties_info","properties"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"},"info":{"$ref":"#/components/schemas/TextField"},"properties_info":{"$ref":"#/components/schemas/TextField"},"properties":{"$ref":"#/components/schemas/OpsKeyProperties"}}}}}},"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"},"OpsKeyProperties":{"type":"object","required":["version","profile","tag","created_at","lifecycle"],"properties":{"version":{"const":1},"profile":{"enum":["hybrid-performance-v1","hybrid-standard-v1","hybrid-high-assurance-v1","hybrid-long-term-v1","custom"]},"tag":{"$ref":"#/components/schemas/TextField"},"created_at":{"$ref":"#/components/schemas/Timestamp"},"lifecycle":{"$ref":"#/components/schemas/OpsKeyLifecycle"}}},"Timestamp":{"type":"string","pattern":"^[0-9]+$"},"OpsKeyLifecycle":{"type":"object","required":["status","reason","changed_at"],"properties":{"status":{"$ref":"#/components/schemas/LifecycleStatus"},"reason":{"$ref":"#/components/schemas/TextField","maxLength":128},"changed_at":{"type":"string"}}},"LifecycleStatus":{"type":"string","enum":["active","disabled","retired","compromised","destroyed"]},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}}},"responses":{"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/keys/reload":{"post":{"tags":["Keys"],"summary":"Refresh local key state from storage","description":"Administrative operation. Reloads and decrypts keys plus encrypted lifecycle properties from storage into this node's memory. Uses POST because it changes server memory state.","responses":{"200":{"description":"Refreshed loaded key list with decrypted properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListKeysPropertiesOutput"}}}},"default":{"$ref":"#/components/responses/Error"}}}}}}
```

## List keys loaded in local memory with properties

> Administrative endpoint. Lists keys and decrypted lifecycle properties currently loaded in this node's in-memory state. The info field is AAD for keys; properties\_info is AAD for properties.

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"ListKeysPropertiesOutput":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"object","required":["kid","info","properties_info","properties"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"},"info":{"$ref":"#/components/schemas/TextField"},"properties_info":{"$ref":"#/components/schemas/TextField"},"properties":{"$ref":"#/components/schemas/OpsKeyProperties"}}}}}},"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"},"OpsKeyProperties":{"type":"object","required":["version","profile","tag","created_at","lifecycle"],"properties":{"version":{"const":1},"profile":{"enum":["hybrid-performance-v1","hybrid-standard-v1","hybrid-high-assurance-v1","hybrid-long-term-v1","custom"]},"tag":{"$ref":"#/components/schemas/TextField"},"created_at":{"$ref":"#/components/schemas/Timestamp"},"lifecycle":{"$ref":"#/components/schemas/OpsKeyLifecycle"}}},"Timestamp":{"type":"string","pattern":"^[0-9]+$"},"OpsKeyLifecycle":{"type":"object","required":["status","reason","changed_at"],"properties":{"status":{"$ref":"#/components/schemas/LifecycleStatus"},"reason":{"$ref":"#/components/schemas/TextField","maxLength":128},"changed_at":{"type":"string"}}},"LifecycleStatus":{"type":"string","enum":["active","disabled","retired","compromised","destroyed"]},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}}},"responses":{"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/keys/properties":{"get":{"tags":["Keys"],"summary":"List keys loaded in local memory with properties","description":"Administrative endpoint. Lists keys and decrypted lifecycle properties currently loaded in this node's in-memory state. The info field is AAD for keys; properties_info is AAD for properties.","responses":{"200":{"description":"Loaded key list with properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListKeysPropertiesOutput"}}}},"default":{"$ref":"#/components/responses/Error"}}}}}}
```

## Return decrypted properties for one key

> Administrative endpoint. Returns decrypted lifecycle properties for one key. If the key is not currently loaded in memory, Vectis attempts to load it from storage first.

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"parameters":{"Kid":{"name":"kid","in":"path","required":true,"schema":{"$ref":"#/components/schemas/Kid"}}},"schemas":{"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"KeyPropertiesOutput":{"type":"object","required":["kid","info","properties_info","properties"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"},"info":{"$ref":"#/components/schemas/TextField"},"properties_info":{"$ref":"#/components/schemas/TextField"},"properties":{"$ref":"#/components/schemas/OpsKeyProperties"}}},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"},"OpsKeyProperties":{"type":"object","required":["version","profile","tag","created_at","lifecycle"],"properties":{"version":{"const":1},"profile":{"enum":["hybrid-performance-v1","hybrid-standard-v1","hybrid-high-assurance-v1","hybrid-long-term-v1","custom"]},"tag":{"$ref":"#/components/schemas/TextField"},"created_at":{"$ref":"#/components/schemas/Timestamp"},"lifecycle":{"$ref":"#/components/schemas/OpsKeyLifecycle"}}},"Timestamp":{"type":"string","pattern":"^[0-9]+$"},"OpsKeyLifecycle":{"type":"object","required":["status","reason","changed_at"],"properties":{"status":{"$ref":"#/components/schemas/LifecycleStatus"},"reason":{"$ref":"#/components/schemas/TextField","maxLength":128},"changed_at":{"type":"string"}}},"LifecycleStatus":{"type":"string","enum":["active","disabled","retired","compromised","destroyed"]},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}}},"responses":{"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/keys/properties/{kid}":{"get":{"tags":["Keys"],"summary":"Return decrypted properties for one key","description":"Administrative endpoint. Returns decrypted lifecycle properties for one key. If the key is not currently loaded in memory, Vectis attempts to load it from storage first.","parameters":[{"$ref":"#/components/parameters/Kid"}],"responses":{"200":{"description":"Key properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyPropertiesOutput"}}}},"default":{"$ref":"#/components/responses/Error"}}}}}}
```

## Update key lifecycle metadata

> Administrative endpoint. Updates encrypted lifecycle metadata for an operational key. Lifecycle status is enforced by cryptographic operations. Allowed transitions are active to disabled/retired/compromised/destroyed, and disabled to active. Retired, compromised, and destroyed are terminal states. Same-status transitions are rejected.

```json
{"openapi":"3.1.0","info":{"title":"Vectis HTTP API","version":"v1"},"tags":[{"name":"Keys"}],"servers":[{"url":"http://127.0.0.1:3000","description":"Local default server over HTTP"},{"url":"https://127.0.0.1:3000","description":"Local HTTPS server when VECTIS_MODE=prod"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"parameters":{"Kid":{"name":"kid","in":"path","required":true,"schema":{"$ref":"#/components/schemas/Kid"}}},"schemas":{"Kid":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"UpdateLifecycleInput":{"type":"object","additionalProperties":false,"required":["status","reason"],"properties":{"status":{"$ref":"#/components/schemas/LifecycleStatus"},"reason":{"$ref":"#/components/schemas/TextField","maxLength":128}}},"LifecycleStatus":{"type":"string","enum":["active","disabled","retired","compromised","destroyed"]},"TextField":{"type":"string","minLength":1,"pattern":"^[^\\x00-\\x1F\\x7F-\\x9F]+$"},"UpdateLifecycleOutput":{"type":"object","required":["kid","lifecycle"],"properties":{"kid":{"$ref":"#/components/schemas/Kid"},"lifecycle":{"$ref":"#/components/schemas/OpsKeyLifecycle"}}},"OpsKeyLifecycle":{"type":"object","required":["status","reason","changed_at"],"properties":{"status":{"$ref":"#/components/schemas/LifecycleStatus"},"reason":{"$ref":"#/components/schemas/TextField","maxLength":128},"changed_at":{"type":"string"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/TextField"}}}},"responses":{"RequestBodyTooLarge":{"description":"Request body exceeds the internal 2 MiB limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Error":{"description":"Public error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/lifecycle/{kid}":{"post":{"tags":["Keys"],"summary":"Update key lifecycle metadata","description":"Administrative endpoint. Updates encrypted lifecycle metadata for an operational key. Lifecycle status is enforced by cryptographic operations. Allowed transitions are active to disabled/retired/compromised/destroyed, and disabled to active. Retired, compromised, and destroyed are terminal states. Same-status transitions are rejected.","parameters":[{"$ref":"#/components/parameters/Kid"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLifecycleInput"}}}},"responses":{"200":{"description":"Updated lifecycle","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLifecycleOutput"}}}},"413":{"$ref":"#/components/responses/RequestBodyTooLarge"},"default":{"$ref":"#/components/responses/Error"}}}}}}
```
