Gating Stripe refunds
Refunds are the textbook case: cheap to automate, expensive to get wrong. Here we
let small refunds through automatically, send medium ones to a human, and block the
absurd ones — all from one check() and three policies.
Install and construct
import Stripe from "stripe";
import { Eda } from "@eda-holding-inc/sdk";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const eda = new Eda({ apiKey: process.env.EDA_API_KEY! });Gate the refund
export async function refundCharge(chargeId: string, amount: number, customerId: string) {
const decision = await eda.check({
agent: "support-agent",
action: "refund_customer",
params: { amount, customerId, chargeId },
});
if (decision.status === "pending") {
// a human needs to approve — see the human-approval guide to wait or defer
return { status: "awaiting_approval", actionId: decision.actionId };
}
if (decision.status !== "approved") {
return { status: "blocked", reason: decision.reason };
}
const refund = await stripe.refunds.create({ charge: chargeId, amount });
return { status: "refunded", refund };
}Add the tiered policies
In the dashboard → Policies:
| Priority | Action | Condition | Effect |
|---|---|---|---|
| 300 | refund_customer | amount > 5000 (i.e. > $50.00 in cents? use your unit) | block |
| 200 | refund_customer | amount > 500 | require_approval |
| 100 | refund_customer | — | allow |
Pick a consistent unit for amount (dollars or cents) and use it everywhere —
in the params you send and in the policy conditions. Mixing them is the most common
bug in refund gating.
Test it from the CLI first
Before shipping code, prove the policies behave:
eda check support-agent refund_customer '{"amount": 300}' # → approved
eda check support-agent refund_customer '{"amount": 900}' # → pending
eda check support-agent refund_customer '{"amount": 9000}' # → blockedOptional: block refunds to flagged customers
Add a higher-priority policy with a condition on your own signal — pass it in
params so Eda can see it:
await eda.check({
agent: "support-agent",
action: "refund_customer",
params: { amount, customerId, chargeId, customerFlagged: await isFlagged(customerId) },
});Policy: refund_customer where customerFlagged == true → require_approval
(priority above the allow). Now flagged customers always route to a human,
regardless of amount.
What you get
Every refund attempt — approved, paused, or blocked — is now in your audit log with the amount, customer, the policy that fired, and (for approvals) who signed off.