Product4 min

Ship log — March 2026

Custom action buttons, agent identity on every approval, invite-link sharing, and the quiet infra work behind the scenes.

FinalApproval Team
// ship log

March was quieter on the surface and busier underneath. Four things shipped, plus infrastructure work that will not show up in any changelog but made the product noticeably better.

Custom action buttons

Channels can now define named actions beyond Approve and Deny. The two defaults are unchanged. On top of them, a channel owner can add up to three custom actions — Approve with edit, Escalate, Send for rewrite — each with its own label and outcome value on the webhook payload.

Why: a handful of builders were encoding second-order decisions into the denial reason field. Deny, and please rewrite the subject line typed into the reason box, parsed by the agent, branched on. That works but is fragile — one typo and the agent ignores the instruction. A named action gives the branching a proper contract.

The cap is three per channel. Past three, the card starts looking like a vending machine and the speed-to-decision budget on the approval UI page falls apart. If three is not enough, that is a signal the channel is doing too much.

Agent identity on every approval

Every approval now shows the submitting agent's name and version in the header strip above the title. Small, grey text. You stop seeing it after a day. But when you need it, you need it badly.

The case that pushed us: a team running three agents against the same channel — staging, production, and a weekend experimental build. Approvals looked identical on the dashboard. The experimental one was making slightly worse decisions, and nobody could tell which approvals came from which agent without digging into raw request data.

On the submission side, pass agent: { name, version } on the request and it surfaces on the card and in history. Omit it and the card shows nothing, same as before.

Adding an approver used to require an email round-trip. Owner types the email, we send an invitation, person clicks, signs up, joins. For most cases, right shape.

For the cases where it isn't — a solo dev bringing in a co-founder sitting next to them, or a small team onboarding three people in a meeting — we added shareable invite links. The owner generates a link, sends it over whatever channel they want, the invitee clicks, signs up, joins. No email to mistype. No check your spam folder.

The link is scoped to the organization, expires after 7 days, and can be revoked from the page it was created on. Seat limits still apply — the seat count syncs to the subscription quantity. More on the organizations page.

Webhook delivery logs got more visible

The delivery log existed since launch, but was buried at the bottom of the channel detail page behind a Show recent deliveries toggle. This month we promoted it.

It now shows inline, with the most recent 20 attempts visible by default, color-coded by status. A failed delivery shows status code, error string, attempt number, and next retry time. A successful one shows round-trip time — a useful signal when a receiver is slow-failing under load.

None of this is new data. Moving it up the page has changed how often builders notice a webhook problem, which was the point. More on the webhook delivery page.

Quiet infra work

The dashboard is meaningfully faster on accounts with large approval histories. The page that took ~900ms for a user with 10,000+ approvals now loads in ~180ms. A missing compound index on (channel_id, status, created_at) was turning the approvals list query into a sort on a million rows.

The retry worker got a small rewrite. Before, a single receiver returning slow 500s could hog worker slots and delay other channels' deliveries. Now the retry pool is fair-scheduled across channels, so one misbehaving endpoint cannot starve the queue.

And we wrote the internal runbook for secret rotation. Next time someone asks what happens if a secret leaks, the answer is we rotate it, here is the command, it takes under a minute.

That is March. April's log will have fewer line items and one larger one.

Keep reading