Skip to main content
Tally is in active development. This page logs notable changes — new endpoints, new SDK methods, behavior changes, deprecations — so you can track what’s safe to depend on and what’s recently moved. Entries are reverse-chronological. Significant breaking changes will get their own callout; minor improvements roll up into the date entry.

2026-05-29 — Developers tab + billing hardening

A small follow-up week to the go-live release. The dashboard’s developer surfaces are now under one tab, and three billing edge cases that could double-bill or unexpectedly downgrade a paid account are fixed.

Changed

  • Developers tab. API keys and webhooks are now consolidated under a single Developers entry in the dashboard sidebar — matching the Stripe / Vercel / Clerk layout. Both views are stacked as sections on /developers; the webhook detail page moves to /developers/webhooks/{id}. The old /api-keys, /webhooks, and /webhooks/{id} URLs redirect, so existing bookmarks and the onboarding checklist still work.

Fixed

  • Duplicate subscriptions on upgrade. Upgrading from Pro to Scale via the account page could mint a second subscription on top of the existing one (so the account paid both plans in parallel). Checkout now rejects with 409 if the customer already has an active subscription, and the account page only shows upgrade buttons to Developer-plan accounts. Paid plans switch in place via Manage billing (Stripe Customer Portal). See the account tab notes.
  • Cancelling one subscription no longer downgrades a still-paying account. If an account ended up with two subscriptions and one was cancelled, the cancellation webhook used to drop the whole account back to Developer. It now checks for any other active subscription on the same customer and keeps the surviving plan.
  • Stale Stripe customer IDs self-heal. Accounts that carried a sandbox Stripe customer ID into live mode were hitting 500s when opening Checkout. The checkout flow now detects a missing or deleted customer, clears the stored ID, and provisions a fresh one transparently — no user-visible error.

2026-05-27 — Out of public preview · plan tiers + Stripe billing

Tally is no longer framed as a public preview. The status pill, legal pages, and docs now describe the product as live on Base, full stop. There’s no functional regression in this entry — same SDK, same dashboard, same APIs — but plan enforcement, the account tab, and the Stripe billing surface all land in this release.

Added

  • Plan-tier enforcement. accounts.plan (Developer / Pro / Scale / Enterprise) now drives the wallet, agent, and monthly sponsored-transaction caps directly from src/lib/plan-limits.ts. The pricing page imports the same module, so marketing copy and enforcement can’t drift.
  • Sponsored-transaction monthly cap. Hard block at the plan’s monthly allowance — Free 1,000 / Pro 50,000 / Scale unlimited — counted across live-mode outbound sends, reset on the 1st of each UTC calendar month. Returns plan_cap_exceeded (HTTP 403) from POST /v1/payments.
  • Agent limit enforcement. Matches the existing wallet cap. New agent creation 400s with validation_failed once the cap is reached; the dashboard’s “New agent” button now also greys out at the cap with an upgrade tooltip.
  • Account tab. New Account nav item on the dashboard. Profile (display name, email, member-since), plan + usage meters (wallets, agents, sponsored sends), account settings (account name, intended use), and a “Danger zone” delete-account flow with type-to-confirm + live-mode USDC balance gate.
  • Stripe billing. /api/stripe/checkout, /api/stripe/portal, /api/stripe/webhook. Yearly billing is offered alongside monthly for Pro and Scale (~17% saving). The webhook syncs account.plan / planRenewsAt / planCancelAt on customer.subscription.{created,updated,deleted}. Deleting an account also cancels the active Stripe subscription.

Changed

  • Pricing page. Replaced the “100 / 25,000 / 250,000 transactions per month” framing with sponsored-transaction allowances: 1,000 / 50,000 / Unlimited. Wallets are now stated as “X per mode (test + live)” to match enforcement. Added a monthly/yearly billing toggle.
  • Wallet cap. No longer a hardcoded constant; reads the user’s plan. Same 3-per-mode default on Developer, but Pro/Scale/Enterprise now actually unlock more.
  • Gas sponsorship caps simplified. The preview-era per-wallet and per-account daily 1dollarcapsareremovedtheyconflictedwithpaidplanusage(Proat50,000sponsoredsends/moaverages 1 dollar caps are removed — they conflicted with paid-plan usage (Pro at 50,000 sponsored sends/mo averages ~8/day in gas) and were redundant with the new monthly hard block. Per-API-key rate limiting (30/min on payments) still prevents single-key abuse. The app-wide circuit breaker stays as catastrophe insurance; its default is now 500/day(was500/day (was 10) and is env-overridable via GAS_CAP_APP_DAILY_USD.
  • Landing page. The status pill reads simply “Live on Base”. Hero and closing-CTA copy dropped “Free during public preview”.
  • Legal pages. Terms and Privacy keep their risk disclaimers but no longer characterize the product as a public preview. Waitlist references removed from the Privacy Policy.
  • Docs. The introductory Note no longer calls Tally a public preview.

Removed

  • Mainnet waitlist. The MainnetWaitlistForm, /api/waitlist, the welcome email helper, and the waitlist_entries table are all gone. Tally is live; there’s nothing to wait for.

Migration required

Run pnpm db:migrate (or npm run db:migrate) to apply 20260527000000_plan_billing_and_user_display_name. It adds the Plan and BillingCycle enums, the plan/Stripe columns on accounts, users.display_name, accounts.deleted_at, and drops waitlist_entries.

2026-05-22 — @tallyforagents/mcp-server (MCP integration)

Added

  • @tallyforagents/mcp-server@0.1.0 — local stdio Model Context Protocol server. Any MCP-aware AI agent (Claude Desktop, Cursor, Hermes, Cline, Goose) can now get a Tally wallet with four lines of config and zero code changes. Exposes four tools: pay_x402_service (any URL, auto-pay on 402), pay_direct (send USDC to an address), list_recent_payments, get_wallet_info (caps + dashboard URL when no permission yet). Identity defaults to an auto-upserted mcp-default agent; overridable via TALLY_AGENT_ID. See the MCP server reference and the Connect via MCP guide.

2026-05-22 — tally.x402.fetch() helper

Added

  • tally.x402.fetch(url, opts) (SDK 0.3.0) — call any HTTP service that uses the x402 protocol. The SDK handles the full 402 dance for you: initial fetch → parse accepts[] terms → tally.payments.create() → retry with the tx hash in the X-Payment header. Returns { response, payment } — the post-payment response plus a receipt for the payment Tally made on your behalf (or null if no payment was needed). Supports per-call max_amount_usdc cap, idempotency_key, custom memo, method/headers/body pass-through. See SDK x402.
  • @tallyforagents/sdk@0.3.0 on npm — adds the x402 resource. Additive, non-breaking.

Changed

  • paying-weather-agent example — refactored to use tally.x402.fetch() instead of the hand-rolled 402 dance. Same UX, ~70 fewer lines in tools.ts.

2026-05-22 — SDK on npm, onboarding checklist, x402 example

First week of post-launch shipping. The TypeScript SDK is now on npm, the dashboard guides you through first-run setup, and there’s a runnable x402-paying agent example.

Added

  • @tallyforagents/sdk@0.1.0 on npm — install with npm i @tallyforagents/sdk. No more monorepo-only consumption. See installation.
  • account_slug on the agent response (SDK 0.1.1) — tally.agents.upsert/list/get() now include the account’s slug, so SDK callers can render dashboard deep-links when guiding the user through a permission grant. Used by the paying-weather-agent example to surface the exact “go grant a permission here” URL when the agent has no active wallets yet.
  • tally.wallets SDK resource (Phase 1 of the SDK gap batch) — tally.wallets.list() returns every wallet in the API key’s account + mode; tally.wallets.create({ display_name, role_label? }) provisions a new Privy server wallet programmatically (no dashboard click needed). SDK-created wallets are owned by the account’s oldest owner-role member so future signer changes behave identically to dashboard-created ones. See SDK wallets for the full reference. Ships unpublished; next SDK release will bundle it with the rest of the gap-batch resources.
  • tally.payments.list() + tally.permissions.list() with auto-pagination (Phase 2 of the SDK gap batch) — Stripe-style AsyncResourcePage so callers can for await (const p of tally.payments.list({ status: "confirmed" })) { ... } and the SDK transparently pages through. .toArray(n) for a bounded read; .firstPage() / .pageAfter(cursor) for manual paging. Payments list takes status/direction/agent_id/wallet/q filters; permissions list returns each grant with today’s usage + remaining-daily-allowance so agent code can preflight a payment without re-fetching the policy. See SDK payments and SDK permissions.
  • tally.agents.delete() + tally.webhooks.list/create/revoke() (Phase 3 of the SDK gap batch) — closes out the SDK gap batch’s mutating + webhook surfaces. agents.delete(id) is a soft-delete (resurrect-on-re-upsert) that 409s with code: "has_active_grants" if the agent still has non-revoked permissions — explicit consent ordering. webhooks.list/create/revoke round out the resource API alongside the existing verifySignature; create() returns the plaintext signing secret exactly once. Standalone verifySignature export retained for non-class consumers. Schema migration 20260523000000_agent_soft_delete adds agents.deleted_at. See SDK agents and SDK webhooks.
  • @tallyforagents/sdk@0.2.0 on npm — SDK gap batch wrapped. New resources: tally.wallets.*, tally.payments.list(), tally.permissions.list(), tally.agents.delete(), tally.webhooks.list/create/revoke(). Stripe-style AsyncResourcePage for paginated lists. Auto-warning to stderr when the API key is in a rotation grace window — server attaches Tally-Rotation-Grace-Until on every authenticated /v1 response; client surfaces it once per process. Additive, non-breaking across the board.
  • Onboarding checklist — the account overview now walks you through the first-run steps (fund a wallet, register an agent, grant a permission, send a payment) and ticks rows off as they complete. Inbound deposits flip the “Fund your wallet” step the moment they land. Each step also has a manual mark-complete escape hatch if you’ve done it out of band.
  • x402 paying-agent example — a runnable Claude/GPT agent that autonomously pays for an HTTP 402-gated weather endpoint via Tally. Hosted demo endpoint included — the example points at it by default, so you can run it end-to-end without standing up your own server. Full walkthrough: Build an x402-paying agent. Source at pkohler95/tally-examples.
  • agent.wallets on the agent responsetally.agents.get() and friends now return the spendable wallets attached to each agent, so you can show “this agent can pay from” without a second call. See SDK agents.
  • Welcome email — first-time sign-ins now receive a branded welcome email pointing at the docs and dashboard.
  • Terms of Service and Privacy Policy — live at /terms and /privacy. Voltaire Technologies LLC is the named operating entity.
  • Support email — reach the team at support@tallyforagents.com, now surfaced across the dashboard and marketing site.

Changed

  • Grant-permission defaults — the grant flow now defaults to 10pertransactionand10 per transaction** and **100 daily cap, and the daily cap is required (no more accidentally-unbounded permissions). Tune up or down as needed before signing.
  • Wallet cards — click any wallet address on the wallets list to copy it. No more selecting and copying by hand.
  • Agent detail page — the ← All agents back-link moved to the top of the page so you don’t have to scroll to navigate back.

Fixed

  • First sign-in race condition — concurrent requests during initial account provisioning no longer occasionally fail; the first sign-in is now serialized.
  • Permission names with long agent slugs — permission creation no longer fails for agents with longer names; the underlying policy name is now capped at 50 characters automatically.
  • Onboarding “Fund your wallet” — inbound USDC deposits now flip the step to complete on the same render, instead of needing a refresh.
  • Decimal entry in the grant + edit dialogs.1 and .3 (no leading zero) now validate cleanly; previously they were rejected as “must be a positive USDC amount.” Both 0.1 and .1 parse identically.
  • Daily cap allows the exact-at-cap payment — the daily-cap check now uses fixed-point arithmetic (BigInt micro-USDC), so a payment that brings the day total to exactly the configured cap is allowed. Previously, floating-point addition (0.2 + 0.1 → 0.30000000000000004) was wrongly rejecting at-cap payments.
  • insufficient_balance is now a 403 with a typed code — payments that fail because the wallet is out of USDC return a forbidden-typed response with code: "insufficient_balance", not a generic 500. Use the existing AuthenticationError class in the SDK; branch on err.code. See error codes.

Coming next

Same roadmap as 2026-05-18 — programmatic wallet and permission management in the SDK, webhook secret rotation, and live mode opt-in. No timing promises.

2026-05-18 — Public preview launch

The initial docs site and TypeScript SDK v0 go live alongside the dashboard at tallyforagents.com. The product is end-to-end functional on Base Sepolia (testnet); live mode is partially built and ships later.

Added

  • Dashboard — sign-in flow with auto-provisioned account and test-mode wallet on first login; full operational surface at /{slug}/overview with balance charts, top wallets, top agents, recent activity.
  • Wallets — Privy server wallets owned by the account; auto-provisioned on sign-in; additional wallets creatable from the dashboard.
  • Agents — register stable identifiers per autonomous unit you run; per-agent attribution and analytics; status reflects active vs no-permissions.
  • Permissions — passkey-signed policies bounding what each agent can do (per-tx max, daily cap, recipient allowlist, contract allowlist, expiry). Policy enforcement happens inside Privy’s secure enclave.
  • Payments via SDKtally.payments.create() for outbound USDC transfers with two-layer enforcement (Tally pre-check + Privy enclave). Idempotency keys, structured error codes, lazy chain refresh via tally.payments.get().
  • Webhooks — six event types (payment.created, payment.confirmed, payment.failed, inbound.received, permission.granted, permission.revoked) with HMAC-SHA256 signatures (t=…,v1=…), exponential retry schedule (1m → 5m → 15m → 1h → 6h, 6 attempts), 10-second per-attempt timeout, manual replay from the dashboard.
  • API key rotation — 24-hour grace window when rotating; old key keeps authenticating while you roll the fleet. Distinct from hard revoke (immediate). Leaked-key scanner watches public commits.
  • Agent permission rotation — swap a permission’s signing key while keeping policy bounds identical; in-place policy edits for changing terms without rotation.
  • Test mode and live mode partitioning — Stripe-style separation by API key prefix (tly_test_… / tly_live_…). Test mode is fully functional on Base Sepolia today; live mode opt-in lands later.
  • TypeScript SDK@tallyforagents/sdk with agents.upsert/list/get, payments.create/get, webhooks.verifySignature. Typed exception hierarchy (AuthenticationError, NotFoundError, ValidationError, RateLimitError, ConflictError, TallyError).
  • REST API at /v1/* — 5 endpoints (POST /v1/agents, GET /v1/agents, GET /v1/agents/{id}, POST /v1/payments, GET /v1/payments/{id}). Bearer-token auth, mode encoded in key prefix, per-key rate limits (60/min default, 30/min on payments).
  • Documentation surface — Get Started, Concepts, Guides, API reference, SDK reference, Ops. Everything grounded in the actual implementation; gaps explicitly flagged.

Coming next

Tracked in BUILD_LOG.md (the “SDK gaps queued from the docs rewrite” section). Highlights:
  • tally.wallets.list() / tally.wallets.create() — programmatic wallet management.
  • tally.permissions.list({ agent_id? }) — inspect active permissions and remaining allowance from code.
  • tally.permissions.revoke() / tally.permissions.update() — server-prepare → user-confirm flows, since revocation needs the wallet owner’s passkey.
  • tally.payments.list({ filters? }) — filterable payment history.
  • tally.agents.delete() — soft-delete with 409 on agents that have active permissions.
  • tally.webhooks.list() / create() / revoke() — endpoint management.
  • Webhook secret rotation with 24h grace window (parity with API key rotation).
  • Live mode opt-in flow and Base mainnet support.
  • ERC-4337 smart-wallet upgrade path (server wallet becomes the signer; trust model carries forward).

Known caveats

  • Idempotency is forgiving. Reusing an idempotency_key with a different payload returns the original payment without revalidating — make sure your key derivation is tied to the payload, not just the operation.
  • Live mode isn’t wired up yet. getDashboardMode() is hardcoded to "test" and no tly_live_ keys are issued. Test mode is fully functional.
  • @tallyforagents/sdk is internal-only today. It’s not yet published to npm; consume it from the monorepo for now. (Resolved 2026-05-22 — SDK is now on npm as @tallyforagents/sdk@0.1.0.)

How to read this changelog

  • Added — new endpoints, SDK methods, dashboard features, webhook event types.
  • Changed — behavior shifts in existing surfaces. If the change could break working code, it’ll be called out as a breaking change.
  • Fixed — bug fixes worth mentioning (silent fixes don’t make the log).
  • Deprecated — surfaces that still work but will be removed. Each deprecation entry includes a target removal date.
  • Coming next — things on the immediate roadmap. No promises on timing; included so you can plan around them.
Subscribe to releases on GitHub to be notified when entries land.