SDK reference
Programmatic API for storing, retrieving, and managing encrypted secrets
Secrets SDK reference
Initialize
import { Secrets } from "@cipherstash/stack/secrets"
const secrets = new Secrets({
workspaceCRN: process.env.CS_WORKSPACE_CRN!,
clientId: process.env.CS_CLIENT_ID!,
clientKey: process.env.CS_CLIENT_KEY!,
apiKey: process.env.CS_CLIENT_ACCESS_KEY!,
environment: "production",
})The environment parameter isolates secrets — each environment gets its own encryption keyset, providing cryptographic isolation.
Store a secret
Encrypts the value locally, then sends the ciphertext to the API:
const result = await secrets.set("DATABASE_URL", "postgres://user:pass@host:5432/db")
if (result.failure) {
console.error("Failed:", result.failure.message)
// result.failure.type: "ApiError" | "NetworkError" | "ClientError" | "EncryptionError"
} else {
console.log(result.data.message) // success message
}Retrieve a single secret
Fetches the encrypted value from the API, decrypts locally:
const result = await secrets.get("DATABASE_URL")
if (!result.failure) {
console.log(result.data) // "postgres://user:pass@host:5432/db"
}Retrieve multiple secrets
Fetch and decrypt multiple secrets in a single call:
const result = await secrets.getMany(["DATABASE_URL", "API_KEY", "JWT_SECRET"])
if (!result.failure) {
console.log(result.data.DATABASE_URL)
console.log(result.data.API_KEY)
console.log(result.data.JWT_SECRET)
}getMany requires a minimum of 2 secret names and a maximum of 100 names per request.
Use
getManyover multiplegetcalls — it's significantly more efficient because it batches the decryption into a single ZeroKMS operation.
List secrets
List all secret names in the current environment. Values stay encrypted — only metadata is returned:
const result = await secrets.list()
if (!result.failure) {
for (const secret of result.data) {
console.log(secret.name)
// Also available: secret.createdAt, secret.updatedAt, secret.environment
}
}Delete a secret
const result = await secrets.delete("OLD_API_KEY")
if (result.failure) {
console.error("Failed:", result.failure.message)
}API summary
| Method | Signature | Returns |
|---|---|---|
set | (name: string, value: string) | Promise<Result<{ success: true, message: string }, SecretsError>> |
get | (name: string) | Promise<Result<string, SecretsError>> |
getMany | (names: string[]) (min 2, max 100) | Promise<Result<Record<string, string>, SecretsError>> |
list | () | Promise<Result<SecretMetadata[], SecretsError>> |
delete | (name: string) | Promise<Result<{ success: true, message: string }, SecretsError>> |
All operations return Result<T, SecretsError> with either data or failure.
Type reference
SecretsConfig
interface SecretsConfig {
workspaceCRN: string // Cloud Resource Name
clientId: string // Client identifier
clientKey: string // Client key material
apiKey: string // API access key (CS_CLIENT_ACCESS_KEY)
environment: string // Environment name
accessKey?: string // Optional additional access key
}SecretMetadata
interface SecretMetadata {
id: string
name: string
environment: string
createdAt: string
updatedAt: string
}Error types
type SecretsErrorType =
| "ApiError" // HTTP/API failures
| "NetworkError" // Network connectivity issues
| "ClientError" // Client initialization failures
| "EncryptionError" // Encryption operation failed
| "DecryptionError" // Decryption operation failedPatterns
Loading secrets at startup
import { Secrets } from "@cipherstash/stack/secrets"
const secrets = new Secrets({
workspaceCRN: process.env.CS_WORKSPACE_CRN!,
clientId: process.env.CS_CLIENT_ID!,
clientKey: process.env.CS_CLIENT_KEY!,
apiKey: process.env.CS_CLIENT_ACCESS_KEY!,
environment: process.env.NODE_ENV || "development",
})
// Load all needed secrets in one efficient call
const result = await secrets.getMany(["DATABASE_URL", "STRIPE_KEY", "SENDGRID_KEY"])
if (result.failure) {
throw new Error(`Failed to load secrets: ${result.failure.message}`)
}
const config = result.data
// Use config.DATABASE_URL, config.STRIPE_KEY, etc.Environment isolation
Each environment has its own encryption keyset, providing cryptographic isolation:
// Production secrets
const prodSecrets = new Secrets({ ...creds, environment: "production" })
// Staging secrets (completely isolated keys)
const stagingSecrets = new Secrets({ ...creds, environment: "staging" })A secret set in one environment cannot be decrypted with credentials from another environment.
How it works
- The SDK encrypts secrets locally using
@cipherstash/stackbefore any network call. - Encrypted values are sent to the CipherStash API over HTTPS.
- CipherStash stores them in your workspace's isolated vault.
- On retrieval, the encrypted value is fetched and decrypted locally by the SDK.
CipherStash never has access to your plaintext secrets. Each workspace has its own isolated vault, and each environment uses a separate encryption keyset managed by ZeroKMS.