Attestations Endpoints
Attestations let agents prove claims about their memories to other agents without revealing the actual content. zkStash signs claims with Ed25519, enabling local verification without API calls.
For conceptual overview and use cases, see Attestations Concepts.
Create Attestation
Create a signed attestation about your memories. The attestation can be shared with other agents to prove claims without revealing actual memory content.
Endpoint: POST /attestations
Cost: 3 CC
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
claim | string | Yes | The type of claim to attest. |
query | string | Conditional | Search query (required for has_memories_matching). |
filters | object | No | Filters for the search (agentId, kind, tags). |
threshold | number | Conditional | Minimum count (required for memory_count_gte). |
schemaName | string | Conditional | Schema name (required for has_schema). |
expiresIn | string | No | Attestation validity duration (default: "24h"). |
Claim Types
| Claim | Description | Required Params |
|---|---|---|
has_memories_matching | Agent has memories matching a query | query |
memory_count_gte | Agent has ≥ N memories | threshold |
has_schema | Agent has a registered schema | schemaName |
Example: Prove You Have Matching Memories
{
"claim": "has_memories_matching",
"query": "cooking recipes",
"filters": {
"agentId": "recipe-bot",
"kind": "Recipe"
},
"expiresIn": "24h"
}Example: Prove Memory Count
{
"claim": "memory_count_gte",
"threshold": 10,
"filters": {
"kind": "Interaction"
}
}Example: Prove Schema Exists
{
"claim": "has_schema",
"schemaName": "UserProfile"
}Response
{
"success": true,
"attestation": {
"claim": "has_memories_matching",
"params": {
"query": "cooking recipes",
"filters": { "agentId": "recipe-bot", "kind": "Recipe" }
},
"result": {
"satisfied": true,
"matchCount": 15,
"namespace": "0x7f3a9c2b..."
},
"issuedAt": 1703123456,
"expiresAt": 1703209856,
"issuer": "zkstash.ai"
},
"signature": "0x...",
"publicKey": "0x...",
"algorithm": "Ed25519"
}Verifying Attestations
Attestations use Ed25519 signatures and are verified locally—no API call required.
1. Get the Public Key
Fetch the public key once and cache it:
curl https://api.zkstash.ai/.well-known/zkstash-keys.json{
"attestationPublicKey": "0x...",
"algorithm": "Ed25519",
"issuedAt": 1703123456789
}2. Serialize the Attestation
Create a canonical JSON string with sorted keys (deterministic serialization):
{
"claim": "has_memories_matching",
"expiresAt": 1703209856,
"issuedAt": 1703123456,
"issuer": "zkstash.ai",
"params": {
"filters": { "agentId": "recipe-bot", "kind": "Recipe" },
"query": "cooking recipes"
},
"result": {
"matchCount": 15,
"namespace": "0x7f3a9c2b...",
"satisfied": true
}
}3. Verify the Signature
Use any Ed25519 library to verify:
Python:
from nacl.signing import VerifyKey
import json
def verify_attestation(attestation: dict, signature: str, public_key: str) -> bool:
# Canonical JSON (sorted keys)
message = json.dumps(attestation, sort_keys=True, separators=(',', ':'))
# Remove 0x prefix and convert
sig_bytes = bytes.fromhex(signature[2:])
key_bytes = bytes.fromhex(public_key[2:])
verify_key = VerifyKey(key_bytes)
try:
verify_key.verify(message.encode(), sig_bytes)
return True
except:
return FalseNode.js (without SDK):
import { verify } from "@noble/ed25519";
function verifyAttestation(attestation, signature, publicKey) {
// Canonical JSON (sorted keys)
const message = JSON.stringify(attestation, Object.keys(attestation).sort());
const sigBytes = Buffer.from(signature.slice(2), "hex");
const keyBytes = Buffer.from(publicKey.slice(2), "hex");
return verify(sigBytes, Buffer.from(message), keyBytes);
}4. Check Expiration
Always verify expiresAt > currentTime before trusting the attestation.
TypeScript SDK: Use
client.verifyAttestation()for a simpler API. See SDK Attestations.
Source Attestations in Search
When searching shared memories via grants, the response includes source attestations that prove provenance:
{
"success": true,
"memories": [
{
"id": "mem_123",
"kind": "ResearchFinding",
"metadata": {
"topic": "AI agents",
"contentHash": "0x7f3a9c2b..."
},
"source": "shared",
"grantor": "0xAgentA..."
}
],
"sourceAttestations": {
"0xAgentA...": {
"attestation": {
"claim": "shared_memories_from",
"params": {
"grantor": "0xAgentA...",
"memoryHashes": ["0x7f3a9c2b..."]
},
"result": {
"satisfied": true,
"matchCount": 1,
"namespace": "0x..."
},
"issuedAt": 1703123456,
"expiresAt": 1703209856,
"issuer": "zkstash.ai"
},
"signature": "0x..."
}
}
}The source attestation proves:
- Memories came from the claimed grantor’s namespace
- zkStash vouches for the provenance
- Memory hashes match what was returned