Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tallyforagents.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let your app react to on-chain events without polling. Tally signs every delivery with HMAC-SHA256.

Register an endpoint

From the dashboard, Webhooks → New endpoint. Choose the events you want to receive:
  • payment.confirmed
  • payment.failed
  • payment.received
  • grant.created
  • grant.revoked

Verifying the signature

Every request carries a Tally-Signature header. The signature is HMAC-SHA256(secret, timestamp.body) where secret is the endpoint’s signing key.
import crypto from "node:crypto";

function verify(req: Request, secret: string): boolean {
  const sig = req.headers.get("tally-signature");
  const ts = req.headers.get("tally-timestamp");
  if (!sig || !ts) return false;

  const body = req.body; // raw bytes
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.${body}`)
    .digest("hex");

  // Constant-time comparison
  return crypto.timingSafeEqual(
    Buffer.from(sig, "hex"),
    Buffer.from(expected, "hex"),
  );
}
Reject events older than 5 minutes to defeat replay attacks. Tally includes a tally-timestamp header on every delivery for exactly this.

Payload shape

{
  "id": "evt_01HXYZ...",
  "type": "payment.confirmed",
  "created_at": "2026-05-16T12:00:00Z",
  "data": {
    "agent_id": "research-bot",
    "tx_hash": "0xabc...",
    "amount_usdc": "4.50",
    "to": "0x7a3f...",
    "memo": "arxiv API access"
  }
}

Retry semantics

Tally retries non-2xx responses with exponential backoff for up to 24 hours, then marks the event as failed in the dashboard. You can manually replay failed events.

Best practices

  • Acknowledge fast — return 2xx within 5 seconds. Defer expensive work to a background job.
  • Be idempotent — Tally may deliver an event more than once.
  • Pin your endpoint’s signing secret in a secret store, not your repo.