Approval routing

Not every team lives in Slack. Route approvals where your humans actually are.

When an agent action needs a human, the question isn't only should this run? It's who sees it, and how fast? ifivo ships a built-in approval queue plus Slack, email, and a generic signed-webhook channel that reaches PagerDuty, Opsgenie, Grafana OnCall, Twilio SMS, n8n, Zapier, or anything that speaks HTTPS.

The in-app queue is on every plan and requires zero integration. Webhook, Slack, and email channels configure in Settings in under five minutes.

Four ways to notify a human

Pick the channels that match your team. Mix freely.

A P1 refund can page your on-call via PagerDuty while a routine vendor addition goes to a Slack channel. Every channel is scoped to the org and can be filtered to P1 only (injection score ≥ 0.6 or amount over your threshold).

In-app approval queue
Built-in

Every pending action lands in /app/approvals with the agent, vendor, amount, destination chip, injection score if any, and one-click Approve / Deny with reason. No external tool required — works on day one.

Available on every plan. No config.
Slack channel
Built-in

Pending approvals post to the channel of your choice with Approve / Deny buttons that hit a signed, short-lived URL. One click in Slack decides the transaction. Per-org signing secret, 7-day link expiry.

Connect in Settings with an Incoming Webhook URL. 2 minutes.
Signed webhook → any on-call tool
Built-in

A generic, HMAC-signed POST channel. Point it at PagerDuty Events v2, Opsgenie, Grafana OnCall, a Twilio SMS relay, n8n, Zapier, or your own listener. Each delivery is signed with a per-channel secret using the same v1.{timestamp}.{body} pattern Stripe and Slack use.

Built-in. You write (or buy) the receiver that translates our event into the target format. We do not ship first-party PagerDuty or Twilio integrations yet.
Email
Optional

Digest and per-event email delivery via your own SMTP relay or Resend. Use it for low-urgency approvals or for stakeholders who don't live in Slack.

Requires SMTP or Resend API key in Settings.
Signed webhooks

One generic channel, four (and counting) destinations.

Our bet: rather than ship a brittle first-party integration for every on-call tool, we give you one well-specified signed webhook and let the last mile live on your side where you already control the mappings, retries, and incident grouping. Here's what teams typically plug in.

PagerDuty

Receiver translates our x-ifivo-event header into a PagerDuty Events API v2 enqueue payload. Severity=critical when injection_score ≥ 0.6 or amount ≥ your P1 threshold.

Opsgenie / Grafana OnCall

Same idea — your receiver maps the severity field and summary string into the upstream alert format.

Twilio SMS

A 20-line relay function verifies our HMAC, builds a short SMS with the summary + approval URL, and posts to the Twilio Messaging API. Scoped to your P1 channel so non-critical approvals don't page you at 3am.

n8n / Zapier / custom

Drop the webhook URL into any automation platform. The signed JSON body gives you the transaction, agent, amount, injection score, destination, and the approval-queue link.

Example delivery

What your receiver gets

POST https://your-endpoint.example.com
x-ifivo-event: approval.pending
x-ifivo-timestamp: 1745420400
x-ifivo-signature: v1=3a7c…9f

{
  "event": "approval.pending",
  "sent_at": "2026-04-23T13:00:00Z",
  "transaction": {
    "id": "tx_01HZ…",
    "agent": "agent:support-bot",
    "vendor": "stripe",
    "action": "refund",
    "amount_cents": 220000,
    "reason": "Amount over per-call ceiling",
    "injection_score": 0.72,
    "destination": { "kind": "email", "value": "attacker@example.com" }
  },
  "severity": "p1",
  "links": {
    "approval_queue": "https://www.ifivo.com/app/approvals",
    "transaction": "https://www.ifivo.com/app/transactions/tx_01HZ…"
  },
  "summary": "agent:support-bot wants to refund via stripe for $2,200.00: Amount over per-call ceiling"
}
Signature verification

Same shape as Stripe / Slack

import crypto from "crypto";

export function verifyIfivo(req, secret) {
  const ts  = req.headers["x-ifivo-timestamp"];
  const sig = req.headers["x-ifivo-signature"]; // "v1=<hex>"
  const raw = req.rawBody.toString("utf8");

  const expected = "v1=" + crypto
    .createHmac("sha256", secret)
    .update(`v1.${ts}.${raw}`)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    throw new Error("bad signature");
  }
  // Reject anything older than 5 minutes to stop replays.
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
    throw new Error("stale");
  }
}
Built-in queue

The answer when your team isn't on Slack.

The in-app approval queue exists on every plan and requires zero integration. It's the durable surface — Slack and webhooks are notifications, the queue is the record. Every pending, approved, and denied action is here, with full context.

Rich context per action

Agent, vendor, action, amount, destination chip, injection score, policy reason, and metadata — on the list view, no drill-in required.

Real-time updates

New pending actions appear without refresh. Stale decisions are marked so approvers know when the request has timed out per your policy.

Decisions are permanent record

Every approve/deny hits the audit log with actor, reason, and signed timestamps. The same feed SIEM exports consume.

Reason required on deny

Denials capture a reason so the pattern can inform future policy — exfiltration destination, broken recipient, wrong agent, over budget.

Webhook fan-out, non-blocking

Every pending approval optionally fans out to your notification channels in parallel. A hung endpoint can't stall the queue or the gateway response.

P1 filter on every channel

Scope any webhook channel to fire only when injection_score ≥ 0.6 or amount ≥ a per-channel threshold. So your on-call pager stays quiet for routine approvals.

When to pick something else

The parts we don't pretend to ship.

First-party on-call integrations. We ship the generic signed webhook, not native PagerDuty / Opsgenie / Twilio adapters. If your team needs a bidirectional PagerDuty integration with incident acknowledgment reflected back into the approval queue, you'll want to build that yourself on top of our webhook, or wait for the first-party version on our roadmap.

Turnkey SMS. Twilio works through a thin relay (roughly 20 lines of code) rather than a Twilio account you connect in our UI. We think that's the right tradeoff for v1; for many teams it's a feature, because the relay is where you also implement on-call rotation.

Approval-as-ticket workflows. If you want every approval to open a Jira/Linear ticket with a custom schema, assignees, and SLA policies, we'd rather you wire that through the webhook into your ticket system than force our opinions into the queue.

Stand up agent approvals before your next incident.

Free tier includes the in-app queue, Slack, and up to three webhook channels. Configure, test-ping, and see real deliveries in the audit log in minutes.