Skip to main content

Technical reference

Capture & integrate

Three ways to get decisions into your ledger. Start recording now: every automated decision becomes a signed, verifiable receipt the moment it is piped in.

How do I send automated decisions to Decision Keep?

A. Dashboard (manual)

Manual dry-runs from Docs → Record a decision. Captures only the core identity (system, agent, version, payload) — not the AI-governance metadata. Good for demos; not the production path.

Record a decision →

B. API. /api/decisions

Any service POSTs its automated decisions here with a session cookie. The supported production path: supply risk, confidence, routing and human-oversight fields for full AI-governance capture.

C. Streaming ingest

Pipe JSONL decision logs (file or tail -F) through scripts/ingest.mjs. Self-throttled to the record budget; parents chains a decision to its upstream events for chain-of-custody.

Payload & signing

Payload minimisation & signing model

Send references, not raw PII in payload - ids, hashes, decision outcomes. What Decision Keep persists and verifies is the hash and signature, not the decision content, so the ledger stays PII-free while remaining fully provable.

Two signing models are supported. By default the server signs with your org key (you control the payload; Decision Keep operates the notary). For the strongest guarantee, sign client-side: hash and sign the decision in your own environment and send the signature with the request. The server verifies the signature and appends it without ever holding your key - so raw decision content need never leave your infrastructure. This is what makes the "independent, immutable, forensic witness" promise literal.

Example

Example API call

curl -b "dk_session=<cookie>" -X POST /api/decisions \
  -H 'content-type: application/json' \
  -d '{"system":"Underwriting","decision_type":"loan-approval",
       "agent":"credit-model","version":"v3",
       "payload":{"application_id":"APP-1","amount":50000},
       "confidence_score":0.92,"risk_score":0.18,
       "routing_outcome":"ASSISTED",
       "human_verifier_id":"reviewer-7"}'

Retries

Idempotency keys on machine ingest

Every receipt is de-duplicated on its content hash, so re-delivering the same decision returns the original receipt instead of appending a second one. That is enough for the published SDKs, which stamp received_at once and resend an identical body on retry.

A hand-rolled client that omits received_at has no stable input: the server stamps the receipt clock, the content hash moves, and a retry after a lost response would record the decision twice. Send an Idempotency-Key header (or its x-dk-idempotency-key equivalent) on /api/integrations/ingest and the server will return the original receipt however many times you retry.

curl -X POST /api/integrations/ingest \
  -H 'content-type: application/json' \
  -H 'x-dk-secret: <integration secret>' \
  -H 'Idempotency-Key: order-8812-attempt-1' \
  -d '{"system":"Underwriting","agent":"credit-model","version":"v3",
       "payload":{"application_id":"APP-1"}}'

Inbound provider webhooks (Salesforce, SAP, Oracle, UiPath, Databricks, Snowflake, Workday, Celonis, Kafka, AWS) need no key: they are de-duplicated on the provider's own message id, which is stable across every redelivery.

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.