SDK Overview

Choose an SDK, understand the common API surface, and start reading secrets.

SikkerKey SDKs provide read-only access to secrets from your application. Every SDK authenticates using the same Ed25519 machine identity as the CLI. No API keys, no tokens, no sessions.

All secret management (create, update, rotate, delete) is done through the dashboard. SDKs and the CLI are read-only — they fetch secrets, they don't modify them.

Choose Your SDK

All five SDKs share the same API surface and behavior. Pick the one that matches your runtime. All SDKs are open source under the MIT license on GitHub.

Common API

Every SDK exposes the same core operations:

OperationWhat it does
getSecret(id)Read a single-value secret
getFields(id)Read a structured secret as key-value pairs
getField(id, field)Read one field from a structured secret
listSecrets()List all secrets this machine can access
listSecretsByProject(projectId)List secrets in a specific project
export(projectId?)Export all secrets as a flat key-value map
listVaults()List vault IDs registered on this machine
watch(id, callback)Watch a secret for changes in near real-time
unwatch(id)Stop watching a secret
setPollInterval(seconds)Set the poll interval (minimum 10 seconds)
close()Stop all watches and shut down polling

Naming conventions vary by language (getSecret in Kotlin/Node, get_secret in Python, GetSecret in Go/.NET), but the behavior is identical.

Identity Resolution

The SDK finds the machine's Ed25519 keypair automatically. Resolution order:

  1. Explicit vault IDSikkerKey("vault_abc123") looks up ~/.sikkerkey/vaults/vault_abc123/identity.json
  2. Explicit pathSikkerKey("/path/to/identity.json") uses a file path directly
  3. Environment variableSIKKERKEY_IDENTITY points to an identity.json file
  4. Auto-detect — if exactly one vault directory exists, uses it automatically

The base directory (~/.sikkerkey/) can be overridden with the SIKKERKEY_HOME environment variable. The vault_ prefix is added automatically if not present.

Authentication

Every request is signed with the machine's Ed25519 private key:

  1. Build the payload: {method}:{path}:{timestamp}:{nonce}:{bodyHash}
  2. Sign with the private key
  3. Send four headers: X-Machine-Id, X-Timestamp, X-Nonce, X-Signature
  4. Server verifies the signature against the stored public key

No tokens are stored, transmitted, or refreshed. Every request is independently authenticated. HTTPS is enforced for all non-localhost connections.

Retry Behavior

All SDKs automatically retry on:

  • 429 Too Many Requests — rate limited
  • 503 Service Unavailable — server sealed or temporarily down

Retry schedule: 1s, 2s, 4s (exponential backoff, max 3 retries). Each retry generates a fresh timestamp and nonce. Network errors are also retried.

Error Handling

All SDKs use a typed exception hierarchy:

ExceptionHTTP StatusMeaning
AuthenticationError401Invalid signature or unknown machine
AccessDeniedError403Machine not approved, disabled, or no grant
NotFoundError404Secret does not exist
ConflictError409Invalid operation
RateLimitedError429Too many requests (retried automatically)
ServerSealedError503Server needs unseal (retried automatically)
ConfigurationErrorIdentity file missing, key not found
SecretStructureErrorSecret is not a JSON object (getFields)
FieldNotFoundErrorField not in structured secret (getField)

Exception class names vary by language convention (e.g. NotFoundError in Node.js, NotFoundException in Kotlin, NotFoundError in Go).

Watching for Changes

All SDKs can watch secrets for changes in near real-time. When a secret is rotated, updated, deleted, or access is revoked, a callback fires with the new value. Polling happens in the background -- your application is never blocked.

// Node.js example -- all SDKs have the same API
sk.watch('sk_db_credentials', (event) => {
  if (event.status === 'changed') {
    db.reconfigure({
      username: event.fields.username,
      password: event.fields.password,
    })
  }
})

The SDK polls the server every 15 seconds (configurable, minimum 10). When a change is detected, the SDK fetches the new value through the normal authenticated path -- every read is audited. Structured secrets are automatically parsed into fields.

Statuses:

StatusMeaning
changedSecret was updated or rotated. New value and parsed fields are provided.
deletedSecret was deleted. Watch is automatically removed.
access_deniedMachine no longer has access. Watch is automatically removed.
errorFailed to fetch the updated value. Error message provided.

See individual SDK pages for language-specific examples.

Multi-Vault

A machine registered with multiple vaults uses a separate keypair per vault:

const prod = SikkerKey.create('vault_production')
const staging = SikkerKey.create('vault_staging')

const dbPass = await prod.getSecret('sk_db_prod')
const testKey = await staging.getSecret('sk_test_key')

Each vault is fully isolated — different keypairs, different encryption keys, different access grants.

Export and Environment Injection

All SDKs can export secrets as a flat key-value map:

const env = await sk.export()
// { API_KEY: "sk-live-...", DB_CREDS_HOST: "db.example.com", DB_CREDS_PASSWORD: "s3cret" }

Structured secrets are flattened: a secret named DB Creds with fields host and password becomes DB_CREDS_HOST and DB_CREDS_PASSWORD.

For CLI-based injection, use sikkerkey run -- ./your-app which exports all secrets as environment variables into the child process.

Environment Variables

VariableDescription
SIKKERKEY_IDENTITYPath to identity.json — overrides vault lookup
SIKKERKEY_HOMEBase config directory (default: ~/.sikkerkey)
SIKKERKEY_VAULTVault ID hint (used by some SDKs for auto-detection)