Technical reference
SDK
Non-blocking TypeScript client for capturing automated decisions. Fire-and-forget recording, bounded retry, and a sendBeacon unload flush mean your application never waits on the ledger.
Installation
Installation
How do I install the @decisionkeep/client package?
npm install @decisionkeep/clientQuick start
Quick start
How do I record my first decision with the SDK?
Import the client, configure it with your instance URL and API key, and call record(). The call returns immediately and never throws.
import DecisionKeepClient from "@decisionkeep/client";
const client = new DecisionKeepClient({
baseUrl: "https://keep.your-co.com",
apiKey: process.env.DECISIONKEEP_API_KEY!,
});
client.record({
system: "Underwriting",
agent: "credit-model",
version: "v3",
payload: { application_id: "APP-1", amount: 50000 },
});
const result = await client.verifyReceipt("RCP-20260710-1A2B3C");
console.log(result);API reference
API reference
record(input: DecisionInput): RecordResultQueue a decision for async dispatch. Returns immediately; never blocks and never throws. The result reports whether the entry was queued, flushed, or dropped (if the bounded buffer overflowed).
const result = client.record({
system: "Underwriting",
agent: "credit-model",
version: "v3",
payload: { application_id: "APP-1", amount: 50000 },
});
// result = { queued: true, flushed: false, dropped: false }verifyReceipt(receipt: string): Promise<VerifyResult>Verify a receipt against the public verification endpoint. Never rejects: on any error it resolves with { ok: false, error }.
const result = await client.verifyReceipt("RCP-20260710-1A2B3C");
// result = { ok: true, receipt: "RCP-20260710-1A2B3C" }dispose(): Promise<void>Flush any buffered entries and stop the retry timer. Call on shutdown (e.g. serverless function teardown, page unload in browser).
await client.dispose();Configuration
Configuration options
Pass an options object to the DecisionKeepClient constructor. All options are optional except baseUrl and apiKey.
| Option | Type | Description | Default |
|---|---|---|---|
| baseUrl | string | Base URL of the Decision Keep instance. | https://decisionkeep.com |
| apiKey | string | Integration/org secret sent as the x-dk-secret header. | - |
| ingestPath | string | Ingest path. Defaults to /api/integrations/ingest. | /api/integrations/ingest |
| provider | string | Integration provider sent as x-dk-provider. Must match an org integration. | aws |
| timeoutMs | number | Hard timeout for a single dispatch (ms). | 2000 |
| bufferSize | number | Bounded in-memory retry buffer size. | 100 |
| flushIntervalMs | number | How often to retry buffered entries (ms). | 5000 |
Error handling
Error handling
The SDK is designed to never throw and never block the caller. Errors are surfaced through result objects:
- •
record()returns{ queued, flushed, dropped, error? }. If the buffer overflows, the oldest entries are dropped and counted indroppedTotal. - •
verifyReceipt()never rejects. It resolves with{ ok, receipt?, error? }. - •Network failures, timeouts, and non-2xx responses are retried with exponential backoff up to 5 attempts. After exhaustion the entry is dropped and counted.
Runtime
Browser vs Node.js
The SDK is dependency-free and runs anywhere with a standard fetch implementation and timers:
- •Browser: Uses
sendBeacon(viakeepalive: true) on page unload to flush the buffer without delaying navigation. - •Node.js / Edge: Uses a background timer for periodic flush. Call
dispose()on shutdown to flush synchronously. - •Serverless: The unref'd timer avoids blocking process exit, and
dispose()flushes pending entries before the function cold-starts.
Source
Source & issues
The SDK lives in the sdk/ directory of the main repository. Report bugs and request features on GitHub:
See the Forensic Witness on your stack
Book a personalised demo and we'll map Decision Keep to your automated-decision obligations and show the evidence trail end to end.