Skip to main content

Quickstart — First Trace in 60 Seconds

This page records one AI decision into Adjudon's tamper-evident SHA-256 hash chain and verifies the row offline. Target: under 60 seconds from a clean install. You ship the trace, we ship the chain row. The integration is one HTTPS call against the production API at api.adjudon.com (Frankfurt eu-central-1); the rest of this site is the operational answer to what happens after that call lands.

Prerequisites

  • Python 3.10+ or Node 18+
  • An Adjudon account (any plan; Sandbox works for this Quickstart)
  • A workspace API key — create one at the dashboard's Settings → API Keys; see Authentication for the format
  • A terminal that lets you set environment variables

Install

Python
pip install adjudon
Node
npm install @adjudon/node
curl (no install)
curl --version   # ensure curl is available

Get an API key

The key looks like adj_live_<64 hex characters>. Create one in the dashboard, copy it from the modal — the raw value appears only once and we cannot recover it — and export it as an environment variable. Do not hardcode the key in source: the prefix is recognised by GitHub's secret scanner and most IDE plugins, so an accidental commit is detected, but the simpler protection is never to write the raw value into a tracked file. See Authentication for the full storage and rotation procedure.

env
export ADJUDON_API_KEY="adj_live_<your-64-hex-key>"
export ADJUDON_BASE_URL="https://api.adjudon.com"

The base URL is Frankfurt eu-central-1; do not point any other host at this. A quick liveness check before sending a real trace:

curl — public health probe
curl https://api.adjudon.com/health
Response (200 OK)
{
"status": "ok",
"service": "adjudon-api",
"version": "1.0.0",
"timestamp": "2026-05-06T10:14:22.317Z",
"uptimeSeconds": 86400,
"checks": { "database": "connected" }
}

/health returns liveness only; it never carries customer data and never requires authentication.

Record your first trace

The single core call: a POST /api/v1/traces with three required fields — agentId, inputContext.prompt, and outputDecision.action. Everything else (rationale, metadata, triggering condition) is optional and passes through to the chain row's payloadDigest. Send the request with an Idempotency-Key header so a network retry does not produce a second trace; the server returns the original response on a duplicate key for 24 hours.

curl
curl -X POST https://api.adjudon.com/api/v1/traces \
-H "Authorization: Bearer $ADJUDON_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"agentId": "underwriter-v1",
"inputContext": {
"prompt": "Loan application: 50000 EUR, 36-month term"
},
"outputDecision": {
"action": "deny",
"rationale": "Income/debt ratio exceeds policy threshold"
}
}'
Python
import os, requests, uuid

r = requests.post(
"https://api.adjudon.com/api/v1/traces",
headers={
"Authorization": f"Bearer {os.environ['ADJUDON_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"agentId": "underwriter-v1",
"inputContext": { "prompt": "Loan application: 50000 EUR" },
"outputDecision": { "action": "deny", "rationale": "..." },
},
)
r.raise_for_status()
print(r.json())
Node
import { randomUUID } from "node:crypto";

const res = await fetch("https://api.adjudon.com/api/v1/traces", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ADJUDON_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({
agentId: "underwriter-v1",
inputContext: { prompt: "Loan application: 50000 EUR" },
outputDecision: { action: "deny", rationale: "..." },
}),
});
console.log(await res.json());

The status code carries product semantics. A successful approve returns 201 Created and the agent should proceed with the action. A flag-for-review returns 202 Accepted and the agent should pause while a human reviews the decision in the Review Queue. A policy block returns 403 Forbidden with code ADJ_BLOCKED_BY_POLICY and the agent must not proceed. The body in every case is the same shape — the status code tells you which path the policy gate took:

Response (201 Created — approved)
{
"success": true,
"data": {
"traceId": "trace_aBcD1234",
"agentId": "underwriter-v1",
"status": "approved",
"confidenceScore": 0.83,
"tags": [],
"matchedPolicy": null,
"createdAt": "2026-05-06T10:14:22.317Z"
}
}

Copy the traceId. The hash-chain row is appended asynchronously (the ingestion path is non-blocking); it is queryable within milliseconds of the response.

Verify on the chain

The hash-chain row is the durable artefact a regulator will eventually read. The trace POST returns synchronously; the chain append runs fire-and-forget and lands within milliseconds. Pull the chain row for the traceId you just received:

curl
curl https://api.adjudon.com/api/v1/hash-chain/entry/trace_aBcD1234 \
-H "Authorization: Bearer $ADJUDON_API_KEY"
Python
r = requests.get(
f"https://api.adjudon.com/api/v1/hash-chain/entry/{trace_id}",
headers={"Authorization": f"Bearer {os.environ['ADJUDON_API_KEY']}"},
)
entry = r.json()["data"]["entry"]
print(entry["sequence"], entry["chainHash"])

The response carries the row's sequence, prevHash, payloadDigest, and chainHash — the four fields the published verify algorithm needs. See Hash Chain API for the full endpoint surface.

The chain is replay-verifiable offline. Run the algorithm yourself against the bundle export at /api/v1/hash-chain/export and you have a procurement-grade audit artefact, no Adjudon login required.

What just happened

Three things, in order. One, the trace was scrubbed of generic PII (email, IBAN, credit-card, SSN, phone) before any storage; what ingested into MongoDB Atlas Frankfurt was the redacted payload, not the raw input. Two, the Confidence Engine triangulated against three independent signals (base probability, variance across ensembles, historical precedent) and produced confidenceScore plus tags. Three, the Policy Engine evaluated the trace against your organisation's active policies and decided 201 / 202 / 403. The chain row anchored the whole sequence into a per-organisation SHA-256 chain that is replay-verifiable offline.

See Audit Log & Security for the chain formula and the four-step verify algorithm.

Common 60-second derailers
  • Wrong base URL. Production lives at https://api.adjudon.com. Pointing a key at any other host returns DNS or 401.
  • 401 INVALID_API_KEY_FORMAT. The key must match adj_live_<64-hex>. A trimmed-down or wrapped value fails the prefix check.
  • 429 RATE_LIMIT_EXCEEDED. Per-agent and per-key limits apply — back off with exponential delay; see Rate Limits.
  • Idempotency-Key reused. A second POST with the same key returns the original response, not a new trace. That is by design.

Next steps