Umbra Trust Protocol
Get to your first verified record in 5 minutes
You'll send an AI decision event to the UTP ledger, verify it with a public endpoint, and confirm it's sealed into an RFC3161-timestamped chain — without touching any infrastructure.
Estimated time: 5 minutes
Prerequisites
You need one API key tied to your organisation. Request access here — keys are typically issued within one business day. The key looks like:
Set it as an environment variable for the examples below:
export UTP_API_KEY="utp_live_your_key_here"
$env:UTP_API_KEY = "utp_live_your_key_here"
Send your first record
POST to /api/v1/records with a JSON body describing the AI decision event. Every record is immediately hashed, chained to the previous entry, and sealed.
$ curl -s -X POST https://kaironull.com/api/v1/records \ -H "Authorization: Bearer $UTP_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "pipeline_id": "loan-approval-v2", "entry_type": "pass", "stage_slug": "credit-check", "summary": "Automated credit check passed for application #8821", "trust_score": 0.91, "model_version": "gemini-2.5-flash", "detail": { "applicant_id": "APP-8821", "score_band": "A", "rule_version": "CREDIT-RULES-2026-Q2" } }'
import os, requests resp = requests.post( "https://kaironull.com/api/v1/records", headers={ "Authorization": f"Bearer {os.environ['UTP_API_KEY']}", "Content-Type": "application/json", }, json={ "pipeline_id": "loan-approval-v2", "entry_type": "pass", "stage_slug": "credit-check", "summary": "Automated credit check passed for #8821", "trust_score": 0.91, "model_version": "gemini-2.5-flash", "detail": { "applicant_id": "APP-8821", "score_band": "A", }, }, ) record = resp.json() print(f"Entry hash: {record['entry_hash']}")
const res = await fetch('https://kaironull.com/api/v1/records', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.UTP_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ pipeline_id: 'loan-approval-v2', entry_type: 'pass', stage_slug: 'credit-check', summary: 'Automated credit check passed for #8821', trust_score: 0.91, model_version: 'gemini-2.5-flash', detail: { applicant_id: 'APP-8821', score_band: 'A' }, }), }) const { entry_hash } = await res.json() console.log(`Hash: ${entry_hash}`)
Response 201 Created
entry_type accepts: pass · flag · block · escalate
Required and optional fields:
| Field | Description |
|---|---|
| pipeline_id required | Your pipeline or process identifier |
| entry_type required | pass · flag · block · escalate |
| stage_slug required | The pipeline stage (e.g. credit-check) |
| summary required | Human-readable description of the decision |
| trust_score optional | 0.0 – 1.0 confidence float |
| model_version optional | Model identifier string |
| data_sources optional | Array of source identifiers |
| detail optional | Arbitrary JSON — stored verbatim |
| input_payload optional | The input that drove the decision |
| system_state optional | Snapshot of relevant system state |
Verify a record
Anyone — including regulators and auditors — can verify a record using its entry_hash. This endpoint requires no authentication.
$ curl -s https://kaironull.com/api/v1/verify/a3f7b2c1d4e5f609...c8d9e0f1
entry_hash = record["entry_hash"] resp = requests.get( f"https://kaironull.com/api/v1/verify/{entry_hash}" ) result = resp.json() if result["found"]: print("✓ Record verified on-chain") if result["anchor"]["anchored"]: print(f" Anchored at {result['anchor']['anchored_at']}") else: print("✗ Hash not found")
const vRes = await fetch( `https://kaironull.com/api/v1/verify/${entry_hash}` ) const { found, anchor } = await vRes.json() if (found) { console.log('✓ Record verified on-chain') if (anchor.anchored) console.log(` RFC3161 anchor: ${anchor.anchored_at}`) } else { console.error('✗ Hash not found') }
Response 200 OK — verified and anchored
false until the next hourly anchor run completes. Records are in the ledger immediately; the RFC3161 timestamp is applied within the hour.
Response — not found
Check chain status
A public endpoint returns the current ledger tip and last anchor. Use it in dashboards, uptime monitors, or compliance checks.
$ curl -s https://kaironull.com/api/v1/chain/status | jq
How the chain works
Each record is linked to the one before it. Altering any record breaks every hash that follows — making the chain tamper-evident by construction.
Every hour, an anchor job runs:
- All
entry_hashvalues are concatenated in chronological order - A SHA-256 root hash is computed over the concatenated bytes
- A DER-encoded RFC3161 TimeStampReq is submitted to FreeTSA
- The signed timestamp token is stored alongside the root hash
umbra_ledger. Records are permanent from the moment they land.
Next steps
Once your first records are flowing, use the reports endpoint to produce a signed evidence bundle — a self-contained JSON package suitable for auditors or regulators.
# Download a full evidence bundle for your org $ curl -s \ -H "Authorization: Bearer $UTP_API_KEY" \ "https://kaironull.com/api/v1/reports?limit=100" \ -o evidence-bundle.json