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.