Attesto

Webhooks

Signed tenant webhooks

Attesto verstuurt signed HTTP POST deliveries voor belangrijke lifecycle events. Je endpoint moet de signature verifiëren, delivery IDs dedupliceren en binnen 10 seconden een 2xx response teruggeven.

Wanneer webhooks gebruiken

Webhooks melden aan je systemen dat Attesto evidence is veranderd. Gebruik ze voor workflow automation: start een interne review wanneer een bundle klaar is, meld een case system wanneer een checkpoint sluit, of pauzeer reliance op een stream wanneer fork evidence verschijnt. Behandel een webhook niet als de evidence zelf. Haal of verifieer de gerefereerde receipt, checkpoint, fork evidence of bundle voordat je erop vertrouwt.

NeedUseWhy
Receive lifecycle notificationsTenant webhooksAttesto roept je endpoint aan nadat evidence verandert.
Send source evidence into AttestoConnectors or SDK/APIJe systeem maakt het event; Attesto receiptt het.
Verify a received bundleOffline verifier or POST /v2/verifyVerification controleert evidence integrity; notification doet dat niet.

Supported events

EventWanneer het fires
batch.confirmedEen Merkle batch van tenant events is on-chain bevestigd.
batch.failedEen batch is permanent gefaald of heeft de orphan window overschreden.
event.anchoredPer-event notification nadat de related batch is bevestigd.
proofstream.checkpointedEen Proofstream checkpoint is gesloten en beschikbaar voor verificatie.
proofstream.fork_detectedFork evidence is aangemaakt voor een stream history conflict.
proofstream.bundle_readyEen verifier bundle is klaar voor de geconfigureerde range.

Maak een subscription

: "${ATTESTO_WEBHOOK_URL:?set this to an HTTPS endpoint controlled by your organization}"

curl -X POST https://dashboard.attesto.eu/v1/webhooks \
  -H "Authorization: Bearer $ATTESTO_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @- <<JSON
{
  "name": "audit-notifications",
  "url": "$ATTESTO_WEBHOOK_URL",
  "eventTypes": ["batch.confirmed", "batch.failed"],
  "description": "Posts lifecycle notifications to the configured endpoint"
}
JSON

Verifieer delivery signatures

Elke delivery bevat deze headers:

Delivery body shape:

{
  "id": "delivery_...",
  "event": "proofstream.bundle_ready",
  "tenant_id": "tenant_...",
  "created_at": "2026-06-07T12:00:00Z",
  "data": {
    "stream_id": "str_...",
    "bundle_id": "bundle_...",
    "from_seq_no": 1,
    "to_seq_no": 250,
    "verification_url": "https://verify.attesto.eu/v2/verify"
  }
}
import hashlib
import hmac
import time

def verify(signing_value: str, body: bytes, timestamp: str, signature: str) -> bool:
    ts = int(timestamp)
    if abs(int(time.time()) - ts) > 300:
        return False
    expected = hmac.new(
        signing_value.encode("ascii"),
        f"{ts}.".encode("ascii") + body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Minimale Node handler

import crypto from "node:crypto";
import express from "express";

const app = express();
app.use(express.raw({ type: "application/json" }));

function verifyDelivery(signingValue, body, timestamp, signature) {
  const ts = Number(timestamp);
  if (!Number.isFinite(ts) || Math.abs(Date.now() / 1000 - ts) > 300) {
    return false;
  }
  const expected = crypto
    .createHmac("sha256", signingValue)
    .update(`${timestamp}.`)
    .update(body)
    .digest("hex");
  const expectedBytes = Buffer.from(expected, "hex");
  const receivedBytes = Buffer.from(signature || "", "hex");
  return expectedBytes.length === receivedBytes.length
    && crypto.timingSafeEqual(expectedBytes, receivedBytes);
}

app.post("/attesto/webhook", async (req, res) => {
  const ok = verifyDelivery(
    process.env.ATTESTO_WEBHOOK_SIGNING_VALUE,
    req.body,
    req.header("X-Attesto-Timestamp"),
    req.header("X-Attesto-Signature"),
  );
  if (!ok) return res.status(401).end();

  const deliveryId = req.header("X-Attesto-Delivery-Id");
  const payload = JSON.parse(req.body.toString("utf8"));
  await recordDeliveryOnce(deliveryId, payload);
  res.status(204).end();
});

Retry en dedupe

Delivery is at least once. Elke non-2xx response, timeout of refused connection wordt opnieuw geprobeerd. Dedupe op X-Attesto-Delivery-Id vóór side effects.

AttemptDelay
1Immediate
230 seconds
32 minutes
410 minutes
51 hour
66 hours
7Final attempt

Endpoint requirements

Gebruik HTTPS, verifieer de raw body vóór parsing, bewaar delivery IDs voor dedupe, return snel en verplaats duur processing naar je eigen queue nadat signature verification is geslaagd.