Receipts, or it didn't happen.
Sentinel turns every action — human or AI — into a hash-chained, tamper-evident receipt. There are only two verbs to learn: seal an action, and verify the chain. Everything else is detail.
Seal an action
Append a receipt to the ledger. Who acted, in what lane, on what, and the result — locked to the receipt before it.
Receipts API →Verify the chain
Re-check every link. Returns PASS, or the exact receipt where integrity broke. No key required — anyone can verify.
Verify endpoint →The verify endpoint is public and keyless today. The ingest API (sealing receipts) is in Founding-Partner preview — request a key. Base URL throughout these docs: https://sentinel.matchain.io/v1.
01 Quickstart
From a key to your first sealed receipt in five minutes.
- Get a key. Founding Partners receive a workspace key. Set it in your environment as
SENTINEL_KEY. - Seal your first action. One POST. Humans and agents use the same call.
- Verify. Re-check the chain — no key needed.
# seal an action
curl -X POST https://sentinel.matchain.io/v1/receipts \
-H "Authorization: Bearer $SENTINEL_KEY" \
-d '{"operator":"agent:planner-7","role":"planner",
"action":"deploy","target":"svc/checkout@1.9.2","scope":"ok"}'
→ { "seq":1069, "hash":"a1f0…e9", "prev":"9c4b…2d" }
# verify the whole chain — no key required
curl https://sentinel.matchain.io/v1/verify
→ { "ok":true, "links":1069, "root":"0x9f4c…e21" }
# pip install sentinel-sdk
from sentinel import Sentinel
s = Sentinel(api_key=os.environ["SENTINEL_KEY"])
r = s.receipts.seal(
operator="agent:planner-7", role="planner",
action="deploy", target="svc/checkout@1.9.2", scope="ok",
)
print(r.seq, r.hash)
v = s.verify()
assert v.ok, f"broken at #{v.broken_at}"
// npm i @sentinel/sdk
import { Sentinel } from "@sentinel/sdk";
const s = new Sentinel({ apiKey: process.env.SENTINEL_KEY });
const r = await s.receipts.seal({
operator: "agent:planner-7", role: "planner",
action: "deploy", target: "svc/checkout@1.9.2", scope: "ok",
});
console.log(r.seq, r.hash);
const v = await s.verify();
if (!v.ok) throw new Error(`broken at #${v.brokenAt}`);
02 Authentication
Sealing receipts is authenticated with a workspace key. Verifying is not — integrity is public by design.
- Bearer key. Send your key as
Authorization: Bearer SENTINEL_KEYon every write. Keys are workspace-scoped; one key can emit for many operators and agents. - Keyless verify.
GET /v1/verifyneeds no credentials. A regulator, a partner, or a stranger can re-check your chain at any time — that is the point. - Rotate freely. Issue and revoke keys per workspace. A revoked key cannot seal new receipts; receipts it already sealed stay valid and attributable.
- Never the content. A key authorizes sealing metadata, never reading your underlying data. Sentinel sells proof of integrity, not access.
03 Receipts API
Two endpoints carry the whole surface. Everything is JSON over HTTPS.
/v1/receipts
Seal one action into the ledger.
Request body fields:
| Field | Type | Required | Description |
|---|---|---|---|
operator | string | yes | Who acted — a human handle or agent:<id>. |
role | string | yes | The lane the operator acted in (e.g. planner, coder, reviewer). |
action | string | yes | What was done (e.g. deploy, payment, read, signoff). |
target | string | yes | What it was done to — a stable identifier. |
scope | string | no | Firewall verdict: ok or denied. Defaults to ok. |
cost_cents | number | no | Metered cost of the action, if you track it. |
meta | object | no | Free-form key/values you want sealed alongside the action. |
/v1/verify
Re-check the chain. Optional ?from=&to= range.
Returns { "ok": true, "links": N, "root": "0x…" } on a clean chain, or { "ok": false, "broken_at": N } pointing at the first receipt whose hash no longer matches. The root is the Merkle root anchored on-chain on a cadence.
04 Receipt schema
What you get back. The last three fields are what make it tamper-evident.
| Field | Type | Description |
|---|---|---|
seq | integer | Monotonic position in the ledger. |
operator · role · action · target · scope | string | The action, exactly as sealed. |
cost_cents | number | Metered cost, if supplied. |
ts | string | RFC-3339 timestamp the receipt was sealed. |
prev | string | Hash of the previous receipt — the link backward. |
hash | string | This receipt's fingerprint (SHA-256 over its fields + prev). Change any field and it no longer matches. |
sig | string | Operator signature over hash. |
05 Errors & rate limits
| Status | Meaning | What to do |
|---|---|---|
401 | Missing or invalid key | Check the Authorization header. Verify needs no key. |
403 | Scope denied | The action is out of the key's lane — recorded, not silent. |
422 | Malformed receipt | A required field is missing or the wrong type. |
429 | Rate limited | Back off; the Retry-After header tells you how long. Quotas scale by plan. |
5xx | Sentinel error | Safe to retry — sealing is idempotent on a client-supplied idempotency_key. |
Free tier is 1,000 reads/day. Paid plans raise the ceiling; the Regulated band is bespoke. Regulator access is unlimited and free, forever.
06 SDKs
Thin wrappers over the same two calls. No SDK required — raw HTTP works from anywhere.
Python
# pip install sentinel-sdk
from sentinel import Sentinel
s = Sentinel(api_key=KEY)
s.receipts.seal(operator="u:ana", role="ops",
action="payout", target="inv:4821")
Node / TypeScript
// npm i @sentinel/sdk
import { Sentinel } from "@sentinel/sdk";
const s = new Sentinel({ apiKey: KEY });
await s.receipts.seal({ operator: "u:ana",
role: "ops", action: "payout", target: "inv:4821" });
Go
// go get sentinel.sh/go
s := sentinel.New(KEY)
s.Receipts.Seal(sentinel.Action{
Operator: "u:ana", Role: "ops",
Action: "payout", Target: "inv:4821",
})
07 Concepts
The architecture, in plain terms — the public half of the whitepaper. No secret sauce, just the load-bearing ideas.
Hash-chain
Each receipt's fingerprint is computed over its own fields plus the previous receipt's hash. Edit any past entry and its hash changes, which breaks the next link, and the next — the verifier rejects everything downstream. History becomes append-only without a database that promises it; the math promises it.
On-chain anchoring
On a cadence, the chain's current Merkle root is stamped onto a public L2 (Matchain). That anchor is a fingerprint of all history up to that point — so even Sentinel cannot rewrite the past after it is anchored. Proof outlives the company.
Firewall-as-code
Scope is a denylist enforced mechanically, not a convention people remember. An out-of-lane action is blocked and recorded as a denied receipt — attributable, never silent. The boundary is in code, so it cannot be quietly skipped.
Consent-gated reads
Reputation derived from receipts is aggregate-only and consent-gated by architecture. No tier, anywhere, unmasks an individual. Sentinel sells verifiability — never the underlying identity.
The full technical whitepaper — threat model, signature scheme, anchoring cadence, and the competency-ladder rollout — is shared with Founding Partners and reviewers under request. Ask for a copy →