Run it by
DocsAPI referencePricingArticles
Sign inGet an API key

In this article

Agents shouldn’t approve their own refundsOne request, several approversThe options that matterAct on the verdict, never on silenceGood habitsAll articles

Use case

Let your agent ask before it spends money: approvals by link

Oct 27, 2026 · 6 min read

Agents shouldn’t approve their own refunds

Once an agent can issue refunds, buy things or grant access, someone will ask “who said yes?”. The answer can’t be “the model decided”. You want a person to approve, you want to know which person, and you want the agent to wait, not guess, when nobody answers.

The people who should approve are often not in your chat tool: a finance lead on their phone, a client’s manager, the owner of a small business. They need a link they can open anywhere, not a seat in your software.

One request, several approvers

An approval is a createRequest with mode: "approval", a reason, and the people who decide. Each person gets their own link, so every decision is attributed to them:

{
  "mode": "approval",
  "title": "Refund #4821",
  "requester": "Ava (the Acme refunds agent)",
  "audience": { "kind": "named", "recipients": [
    { "name": "John Smith", "email": "john@acme.com" },
    { "name": "Martin Carpenter", "email": "martin@acme.com" },
    { "name": "Emily Lee", "email": "emily@acme.com" }
  ] },
  "approval": {
    "reason": "Refund order #4821, $1,200",
    "detail": "Customer reported a damaged item. Photos in ticket T-1042.",
    "policy": "majority",
    "showOthers": "names",
    "verify": "email"
  },
  "expiresIn": "24h",
  "webhookUrl": "https://example.com/hooks/runitby",
  "metadata": { "orderId": "4821" }
}

The options that matter

  • policy decides how many approvals it takes: "any", "all", "majority" or a number. The verdict arrives as soon as it’s decided, without waiting for everyone.
  • verify: "email" makes each person confirm a 6-digit code sent to their own address before the buttons work. A forwarded link can’t decide for them. Use it for money, access or deletion.
  • showOthers lets each approver see where the others stand, by name or as counts.
  • options replaces Approve and Decline with up to four labels, such as “Approve with changes”. The first one counts as approval.
  • allowComment lets people explain their decision; comments come back with it.

Act on the verdict, never on silence

When the policy is met, your webhook gets request.completed with a verdict: "approved", "declined" or "expired" (getStatus returns the same). If nobody decides before the request expires, the verdict is expired. There is no path where no answer turns into a yes.

// Your webhook handler, after checking the X-Runitby-Signature header
if (event.event === 'request.completed') {
  if (event.verdict === 'approved') await refund(event.metadata.orderId)
  else await tellCustomer(event.metadata.orderId, event.verdict)
}

Always verify the webhook signature before acting on it: it’s an HMAC-SHA256 of the raw body with your account’s signing secret. The docs have a ready-made check.

Good habits

  • Put the amount and the order in reason. That’s what people read first, on a small screen.
  • Set an expiresIn that matches the decision. A refund can wait a day; a deploy approval probably can’t.
  • Use metadata to carry your own IDs, so the webhook handler knows what to do without a lookup.
  • Call remind if a deadline is close. It emails pending people again, at most once a day each.

Comparing this with Slack approvals or review inboxes? See Run it by vs approval tools.

Try it with your agent

Free for 100 requests a month, no card. Add the MCP server from Claude Code or Codex with one command, or use the REST API.

Start freeRead the docs

Run it by

Get structured data from a person with a link.

Product

DocsPricingArticles

For agents

MCP setupAPI referencellms.txtopenapi.json

Legal

PrivacyTerms
© 2026 Run it by