POST /v1/receipts
Action, resource, subject and an optional payload — hashed, never stored raw. You get back a signed attested.receipt/v1 and its permanent URL.
Sign any agent action into a document with a permanent, keyless verification URL. Turn those receipts into a passport a hub can check before it lets the agent in. Bind what the world reported to what the agent decided. And let someone prove they belong to a set — exactly once, without revealing which member they are.
Issuing a receipt needs a key. Verifying one never does — not a key, not an account, not even this service, because the document carries its own signature and the public key is published. A receipt nobody can check is worth nothing, so checking is the part that stays free.
Action, resource, subject and an optional payload — hashed, never stored raw. You get back a signed attested.receipt/v1 and its permanent URL.
A human-readable verdict page with the full document and signature printed, so anyone can re-check it offline in any language.
Hand it a document and a signature you were given. No lookup — it either verifies against the published key or it does not.
Signatures are Ed25519, and hybrid ML-DSA-65 when post-quantum mode is on — additive fields over the same canonical string, so a classic verifier still works. Amounts and integers only: a float never enters a signed document, because a receipt signed over 0.1 + 0.2 is a receipt that fails on the other side of the wire.
A passport is a signed slice of what the receipts actually show: how many, how varied, how long the agent has existed, how many world bindings it holds. It states nothing else. Relying parties call GET /v1/gate/{actor} before letting an agent in — free and keyless, because the caller is asking about someone else's agent, and a gate that charges is a gate nobody installs.
Derived from receipt count and age together. A fresh identity with a thousand receipts issued this morning is still new.
Passports go stale on purpose. A reputation snapshot that never expires is a reputation claim, not a measurement.
Revoking is instant and is honoured by the offline verify endpoint and the gate alike, not just by one of them.
An oracle signs an observation — a flood level, a lightning strike, a price. Attested Prove accepts it only from a pinned oracle key, then binds it to an agent's decision as a single signed receipt. The result is one document that answers both halves of "why did it do that?".
# the sensor's word, from a key we pinned in advance POST /v1/world/attest { "document": {…}, "signature": {…}, "subject": "elbe" } # the agent's decision, bound to it POST /v1/memory/bind { "attestation_id": "wrl_…", "memory_id": "mem_…", "decision": "hold the shipment for 24h" } # → one attested.receipt/v1 carrying the oracle key, the observation digest and the decision
A self-asserted key in a signature block proves only that whoever wrote the document also wrote the signature — which is not a fact about the world. So an unpinned oracle is refused outright rather than recorded with a caveat.
Register a set of public keys under a scope. A holder then produces a linkable ring signature: the proof shows that someone in the ring made the claim, and carries a key image that is deterministic for that holder — so a second claim in the same scope is refused, while the holder stays indistinguishable from the rest of the ring.
One vote per member, no roll call of who voted.
"I am on the list" without naming the entry.
"I was verified by someone in this cohort", once per period.
Stated plainly, because privacy products usually are not: this is an LSAG over Ed25519 — a real zero-knowledge membership proof with a real double-spend nullifier. It is not a SNARK. The anonymity set is exactly the ring the verifier is handed, so privacy is bounded by how many keys share the scope — and every scope page prints its own set size, including the case where a ring of one hides nothing.
# the exact bytes to sign — recomputed server-side on submission GET /v1/nullifiers/scopes/$SCOPE/challenge?claim=i-voted # the ring is public, so a verifier can rebuild it independently GET /v1/nullifiers/scopes/$SCOPE # submit — free, and refused if the ring carries a key that is not registered POST /v1/nullifiers/claim { "claim": "i-voted", "proof": { "algorithm": "lsag-ed25519", … } }
Issue receipts, passports and dual-provenance bindings. Verification, gate checks and ring listings never need a key.
Create nullifier scopes and register members. Submitting and verifying claims stays free, for everyone.
/verify/{id}, /v1/receipts/verify, /v1/passports/verify, /v1/gate/{actor}, every scope and spend listing.