tools/SDKs/Node.js SDK

Node.js SDK

Connect Node.js applications to SikkerKey with a machine identity, then read, export, cache, and monitor permitted secrets.

Updated yesterday

The SikkerKey Node.js SDK gives JavaScript and TypeScript applications secure, read-only access to secrets in your vault. Each client uses a machine identity, so the application can retrieve only the secrets and projects that machine is permitted to access.


#Requirements

  • Node.js 18 or later

  • A SikkerKey vault

  • A machine identity with access to the secrets your application needs

The package includes TypeScript declarations and uses only Node.js built-in modules. It is designed for Node.js services, workers, command-line applications, and serverless functions with outbound HTTPS access.

The SDK uses Node.js file-system and cryptography features, so run it in a Node.js environment rather than a browser or browser-style edge runtime.


#Install the SDK

bash
npm install @sikkerkey/sdk

#Read your first secret

typescript
import { SikkerKey } from '@sikkerkey/sdk'

const sikkerKey = SikkerKey.create('vault_...')
const apiKey = await sikkerKey.getSecret('sk_...')

// Pass apiKey directly to the client or service that needs it.

Client creation from a registered identity is synchronous. Secret reads and other network operations return promises and should be awaited.

Do not print secret values or include them in application logs.


#Choose a machine identity

Use a standard machine for persistent servers and workstations. Use an ephemeral machine for short-lived workloads that should keep their identity only in memory.

Use a standard machine

typescript
// Select a registered vault.
const byVault = SikkerKey.create('vault_...')

// Load a specific identity file.
const byPath = SikkerKey.create(
  '/etc/sikkerkey/vaults/vault_.../identity.json',
)

// Use SIKKERKEY_IDENTITY or select the only registered vault.
const automatically = SikkerKey.create()

Automatic selection checks SIKKERKEY_IDENTITY first. If it is not set, the SDK selects the identity when exactly one vault is registered under ~/.sikkerkey/vaults/. Select a vault explicitly when several identities are available.

Set SIKKERKEY_HOME when the application uses a different protected identity directory:

bash
export SIKKERKEY_HOME=/var/lib/sikkerkey

Use an ephemeral machine

typescript
const sikkerKey = await SikkerKey.bootstrap(
  process.env.SIKKERKEY_VAULT_ID!,
  process.env.SIKKERKEY_ENROLLMENT_TOKEN!,
  {
    hostname: 'checkout-worker',
    name: 'Checkout worker',
  },
).inMemory()

const apiKey = await sikkerKey.getSecret('sk_...')

SikkerKey.bootstrap creates an enrollment builder. Calling inMemory() generates an Ed25519 key pair in memory, registers the ephemeral machine, and returns a ready client. No identity or private key is written to disk, and the private key disappears when the process exits.

The machine follows the access, hostname rules, use limit, and lifetime configured on the enrollment token. The hostname defaults to HOSTNAME and then to serverless. A name pattern configured on the token takes precedence over the requested name.

Keep enrollment tokens in protected runtime configuration and set the machine lifetime and token use limit for the workload's duration and expected concurrency.


#Read secrets

Read a standard secret

typescript
const apiKey = await sikkerKey.getSecret('sk_...')

Read a structured secret

typescript
const database = await sikkerKey.getFields('sk_...')

const host = database.host
const username = database.username
const password = database.password

Use getField when the application needs one field:

typescript
const password = await sikkerKey.getField(
  'sk_...',
  'password',
)

Structured values are converted to strings. getFields throws SecretStructureError for a non-object value. getField throws FieldNotFoundError and includes the available field names when a field is missing.


#Discover and export secrets

List the secret metadata available to the current machine:

typescript
const secrets = await sikkerKey.listSecrets()

for (const secret of secrets) {
  console.log(`${secret.id}: ${secret.name}`)
}

Limit the list to one project:

typescript
const secrets = await sikkerKey.listSecretsByProject('proj_...')

Each result includes the secret ID and name, with optional project and structured-field metadata. Listing returns metadata, not secret values.

Export application configuration

typescript
const allConfiguration = await sikkerKey.export()
const projectConfiguration = await sikkerKey.export('proj_...')

Export returns a Record<string, string> in one request. Names use uppercase environment-variable format, and structured secrets are flattened into entries such as DATABASE_HOST and DATABASE_PASSWORD.


#Enable encrypted fallback

Encrypted fallback lets a persistent application use a previously retrieved value during a temporary network or service interruption. It is disabled until enabled.

typescript
const sikkerKey = SikkerKey
  .create('vault_...')
  .enableCache({
    maxAge: 3600,
    onFallback: (secretId, cachedAt) => {
      logger.warn({ secretId, cachedAt }, 'Using cached secret value')
    },
  })

Successful reads are encrypted locally with AES-256-GCM using a key derived from the machine identity and vault. maxAge is measured in seconds; omit it for no automatic expiry. onFallback runs only when the SDK serves a cached value.

Fallback is limited to network failures, timeouts, and temporary gateway or service availability responses. Authentication failures, denied access, missing secrets, rate limits, and other authoritative responses are returned to the application.

Cache entries are bound to the machine, vault, secret, and creation time. The format is compatible with SikkerKey CLI and the other SikkerKey SDKs. Use it with a persistent, protected identity directory.


#Monitor secrets for changes

typescript
sikkerKey.watch('sk_...', (event) => {
  switch (event.status) {
    case 'changed':
      reloadClient(event.value, event.fields)
      break
    case 'deleted':
      logger.warn({ secretId: event.secretId }, 'Secret was deleted')
      break
    case 'access_denied':
      logger.warn({ secretId: event.secretId }, 'Secret access was removed')
      break
    case 'error':
      logger.error({ error: event.error }, 'Secret update failed')
      break
  }
})

The SDK checks watched secrets every 15 seconds by default using an unreferenced timer, so the watcher does not keep an otherwise idle process alive. Changed events include the current value and parsed fields when the secret is structured.

Deleted and inaccessible secrets are removed from the watch list. A failed poll is tried again during a later interval. Keep callbacks short or hand slow work to your application's queue.

typescript
sikkerKey.setPollInterval(30) // seconds; minimum 10
sikkerKey.unwatch('sk_...')
sikkerKey.close()

close() stops monitoring and clears callbacks while leaving the client available for later reads.


#Work with vaults and inspect the client

typescript
const vaultIds = SikkerKey.listVaults()
const production = SikkerKey.create('vault_...')
const staging = SikkerKey.create('vault_...')

Create a separate client for each vault. The active identity is available through machineId, machineName, vaultId, and apiUrl for application diagnostics.


#Handle errors

typescript
import {
  AccessDeniedError,
  ApiError,
  AuthenticationError,
  ConfigurationError,
  NotFoundError,
  RateLimitedError,
} from '@sikkerkey/sdk'

try {
  const value = await sikkerKey.getSecret('sk_...')
} catch (error) {
  if (error instanceof NotFoundError) handleMissingSecret()
  else if (error instanceof AccessDeniedError) handleRemovedAccess()
  else if (error instanceof AuthenticationError) handleAuthenticationFailure()
  else if (error instanceof RateLimitedError) scheduleLaterRetry()
  else if (error instanceof ApiError) recordServiceError(error.httpStatus)
  else if (error instanceof ConfigurationError) handleIdentityConfiguration()
}

All SDK errors extend SikkerKeyError. Typed errors cover configuration, authentication, access, missing resources, conflicts, rate limits, temporary service availability, invalid structured data, and missing fields. Network failures and timeouts use ApiError with httpStatus === 0.

Retries and timeout

Authenticated requests retry network failures, timeouts, and HTTP 429 or 503 responses up to three times, waiting 1, 2, and 4 seconds. Each attempt uses a fresh timestamp and nonce. Requests have a 15-second timeout.


#Method reference

Task

Method

Connect with a registered identity

SikkerKey.create(vaultOrPath?)

Create an ephemeral identity

SikkerKey.bootstrap(...).inMemory()

Read a standard secret

getSecret(secretId)

Read structured fields

getFields(secretId) / getField(secretId, field)

List secrets

listSecrets() / listSecretsByProject(projectId)

Export configuration

export(projectId?)

Enable encrypted fallback

enableCache(options?)

Monitor a secret

watch(secretId, callback)

Stop monitoring

unwatch(secretId) / close()

List local vaults

SikkerKey.listVaults()


#Source code and license

The Node.js SDK is open source under the MIT License. Review the source, report an issue, or contribute through the SikkerKeyOfficial GitHub organization.