Evidence Chain

The Evidence Chain is a tamper-evident audit log of everything that happens in AutopayOS. Every intent, cart verification, payment, and policy decision is recorded with cryptographic hashes that ensure integrity.

Overview

Events are linked in a cryptographic chain:

EventPrevious HashCurrent Hash
Event #1abc123
Event #2abc123def456
Event #3def456ghi789

Each event contains:

  • Data: The event payload
  • Previous hash: Hash of the previous event
  • Current hash: SHA-256 hash of this event + previous hash

If any event is modified, the hash chain breaks, making tampering detectable.

Event types

Event TypeDescriptionTriggered By
INTENT_ISSUEDIntent mandate was approvedIntent creation
INTENT_DENIEDIntent was rejected by policyIntent creation
INTENT_EXPIREDIntent exceeded time limitExpiration
CART_VALIDATEDCart verification passedCart validation
CART_REJECTEDCart verification failedCart validation
PM_ISSUEDPayment mandate was createdPayment execution
PAYMENT_AUTHORIZEDPayment was authorized by railPayment execution
PAYMENT_CAPTUREDFunds were capturedPayment capture
PAYMENT_FAILEDPayment failedPayment failure
ALERT_CREATEDPolicy violation alertVarious
AGENT_REVOKEDAgent was revokedAdmin action

Query evidence

Get recent events

<tabs> <tab title="TypeScript">
TypeScript
const evidence = await client.getEvidence({
  last: 50,
});

console.log('Events:', evidence.events.length);
console.log('Chain valid:', evidence.chainValid);

for (const event of evidence.events) {
  console.log(`${event.eventType} at ${event.createdAt}`);
}
</tab> <tab title="cURL">
Bash
curl "https://api.autopayos.com/ap2/evidence/export?last=50" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"
</tab> </tabs>

Response

JSON
{
  "events": [
    {
      "id": "evt_abc123",
      "seq": 1042,
      "eventType": "INTENT_ISSUED",
      "actorDid": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
      "contextId": "ctx_xyz789",
      "data": {
        "mandateId": "intent_abc123",
        "amount": 50.00,
        "currency": "USD",
        "merchantDomain": "amazon.com"
      },
      "hashPrev": "sha256:abc123...",
      "hashCurr": "sha256:def456...",
      "createdAt": "2025-12-17T10:00:00Z"
    },
    {
      "id": "evt_def456",
      "seq": 1043,
      "eventType": "CART_VALIDATED",
      "actorDid": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
      "contextId": "ctx_xyz789",
      "data": {
        "intentId": "intent_abc123",
        "cartHash": "sha256:cart123...",
        "total": 38.85
      },
      "hashPrev": "sha256:def456...",
      "hashCurr": "sha256:ghi789...",
      "createdAt": "2025-12-17T10:00:05Z"
    }
  ],
  "chainValid": true,
  "fromSeq": 1042,
  "toSeq": 1043
}

Search events

By event type

Bash
curl "https://api.autopayos.com/ap2/evidence/search?eventType=PAYMENT_AUTHORIZED" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"

By agent

Bash
curl "https://api.autopayos.com/ap2/evidence/search?actorDid=did:key:z6Mk..." \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"

By context

Context IDs link related events (e.g., all events for one shopping session):

Bash
curl "https://api.autopayos.com/ap2/evidence/search?contextId=ctx_xyz789" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"

By time range

Bash
curl "https://api.autopayos.com/ap2/evidence/search?from=2025-12-17T00:00:00Z&to=2025-12-17T23:59:59Z" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"

Transaction bundles

Get all evidence for a specific transaction:

<tabs> <tab title="TypeScript">
TypeScript
const bundle = await client.getEvidenceBundle(transactionId);

console.log('Transaction:', bundle.transactionId);
console.log('Events:', bundle.events.length);
console.log('Chain valid:', bundle.chainValid);
console.log('Summary:', bundle.summary);
</tab> <tab title="cURL">
Bash
curl "https://api.autopayos.com/ap2/evidence/bundle/txn_abc123" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"
</tab> </tabs>

Response

JSON
{
  "transactionId": "txn_abc123",
  "events": [
    { "eventType": "INTENT_ISSUED", "seq": 1042 },
    { "eventType": "CART_VALIDATED", "seq": 1043 },
    { "eventType": "PM_ISSUED", "seq": 1044 },
    { "eventType": "PAYMENT_AUTHORIZED", "seq": 1045 },
    { "eventType": "PAYMENT_CAPTURED", "seq": 1046 }
  ],
  "chainValid": true,
  "summary": {
    "agent": "did:key:z6Mk...",
    "principal": "did:key:z6Mp...",
    "merchant": "amazon.com",
    "amount": 38.85,
    "currency": "USD",
    "status": "CAPTURED",
    "startedAt": "2025-12-17T10:00:00Z",
    "completedAt": "2025-12-17T10:00:15Z"
  }
}

Verify chain integrity

Check that the evidence chain hasn't been tampered with:

<tabs> <tab title="TypeScript">
TypeScript
const verification = await client.verifyEvidenceChain({
  fromSeq: 1000,
  toSeq: 1100,
});

if (verification.valid) {
  console.log('Chain integrity verified');
} else {
  console.error('Chain broken at seq:', verification.brokenAt);
}
</tab> <tab title="cURL">
Bash
curl "https://api.autopayos.com/ap2/evidence/verify?fromSeq=1000&toSeq=1100" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY"
</tab> </tabs>

Verification response

JSON
{
  "valid": true,
  "fromSeq": 1000,
  "toSeq": 1100,
  "eventsVerified": 101,
  "verifiedAt": "2025-12-17T10:30:00Z"
}

Or if broken:

JSON
{
  "valid": false,
  "brokenAt": 1050,
  "expectedHash": "sha256:abc123...",
  "actualHash": "sha256:xyz789...",
  "message": "Hash mismatch at sequence 1050"
}

Export evidence

Export evidence for compliance or auditing:

JSON export

Bash
curl "https://api.autopayos.com/ap2/evidence/export?format=json&from=2025-12-01&to=2025-12-17" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY" \
  -o evidence-export.json

CSV export

Bash
curl "https://api.autopayos.com/ap2/evidence/export?format=csv&from=2025-12-01&to=2025-12-17" \
  -H "Authorization: Bearer $AUTOPAYOS_API_KEY" \
  -o evidence-export.csv

Real-time streaming

Subscribe to evidence events via WebSocket:

TypeScript
const ws = new WebSocket('wss://api.autopayos.com/evidence/stream');

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'subscribe',
    token: apiKey,
    filters: {
      eventTypes: ['PAYMENT_AUTHORIZED', 'PAYMENT_FAILED'],
    },
  }));
};

ws.onmessage = (event) => {
  const evidence = JSON.parse(event.data);
  console.log('New event:', evidence.eventType);
};

Event details

INTENT_ISSUED

JSON
{
  "eventType": "INTENT_ISSUED",
  "data": {
    "mandateId": "intent_abc123",
    "agentDid": "did:key:z6Mk...",
    "principalDid": "did:key:z6Mp...",
    "maxAmount": 100.00,
    "currency": "USD",
    "merchantDomain": "amazon.com",
    "policyId": "pol_xyz789",
    "policyVersion": 3,
    "policyHash": "sha256:..."
  }
}

CART_VALIDATED

JSON
{
  "eventType": "CART_VALIDATED",
  "data": {
    "intentId": "intent_abc123",
    "cartHash": "sha256:cart...",
    "merchant": "amazon.com",
    "itemCount": 3,
    "subtotal": 35.97,
    "tax": 2.88,
    "total": 38.85,
    "currency": "USD",
    "rail": "STRIPE"
  }
}

PM_ISSUED

JSON
{
  "eventType": "PM_ISSUED",
  "data": {
    "mandateId": "pm_abc123",
    "intentId": "intent_abc123",
    "amount": 38.85,
    "currency": "USD",
    "merchant": "amazon.com",
    "rail": "STRIPE",
    "expiresAt": "2025-12-17T10:05:00Z"
  }
}

PAYMENT_AUTHORIZED

JSON
{
  "eventType": "PAYMENT_AUTHORIZED",
  "data": {
    "mandateId": "pm_abc123",
    "rail": "STRIPE",
    "railTransactionId": "pi_3abc123...",
    "amount": 38.85,
    "currency": "USD",
    "status": "authorized"
  }
}

Context tracking

Events are grouped by contextId for A2A sessions:

EventContextReference
INTENT_ISSUEDctx_abc123mandateId: intent_001
CART_VALIDATEDctx_abc123intentId: intent_001
PM_ISSUEDctx_abc123mandateId: pm_001
PAYMENT_AUTHORIZEDctx_abc123mandateId: pm_001

Query all events for a session:

TypeScript
const sessionEvents = await client.getEvidence({
  contextId: 'ctx_abc123',
});

Compliance use cases

Audit trail

Generate a complete audit trail for a time period:

TypeScript
const audit = await client.generateAuditReport({
  from: '2025-12-01T00:00:00Z',
  to: '2025-12-31T23:59:59Z',
  includeViolations: true,
  includeSuccessful: true,
});

Policy violation report

Find all policy violations:

TypeScript
const violations = await client.getEvidence({
  eventTypes: ['INTENT_DENIED', 'CART_REJECTED'],
  from: '2025-12-01',
});

Agent activity report

Get all activity for a specific agent:

TypeScript
const agentActivity = await client.getEvidence({
  actorDid: 'did:key:z6Mk...',
  from: '2025-12-01',
});

Best practices

1. Verify regularly

Periodically verify chain integrity:

TypeScript
// Daily verification job
const lastSeq = await getLastVerifiedSeq();
const currentSeq = await getCurrentSeq();

const result = await client.verifyEvidenceChain({
  fromSeq: lastSeq,
  toSeq: currentSeq,
});

if (!result.valid) {
  await alertSecurityTeam(result);
}

2. Store context IDs

Always track context IDs for correlation:

TypeScript
const contextId = `session_${Date.now()}_${agentDid}`;

const permission = await client.requestPermission({
  ...params,
  contextId,
});

// Later: query all events for this session
const events = await client.getEvidence({ contextId });

3. Export for compliance

Regularly export evidence for long-term storage:

TypeScript
// Monthly export
const evidence = await client.exportEvidence({
  from: '2025-12-01',
  to: '2025-12-31',
  format: 'json',
});

await s3.upload({
  Bucket: 'compliance-evidence',
  Key: `evidence-2025-12.json`,
  Body: evidence,
});

Next steps