Stripe
Gate AI-managed Stripe operations — refunds, payouts, subscription changes, charge disputes — behind a human approval step before the Stripe API call executes.
Prerequisites
- Stripe account with server-side API access.
- Cheqpoint Connection Key.
Steps
- Identify AI-driven Stripe operations that need human review (refunds, payouts, subscription cancellations).
- In your server-side code, initialise the Cheqpoint client with your Connection Key.
- Before calling the Stripe API, call
cheq.requestSync()with the transaction details indetails. - If
approved, proceed with the Stripe API call using the effective payload (prefermodifiedDetailsto allow reviewers to adjust amounts). - If
rejected, log the decision and return an appropriate error or message to the caller. - For high-volume systems, use
requestAsync()with acallbackUrlto avoid blocking the payment flow.
Installation
bash
npm install @cheqpoint/sdk stripeSample request payload
json
{
"action": "issue_refund",
"summary": "AI agent requesting full refund for charge ch_3NxYz for $349.00",
"details": {
"charge_id": "ch_3NxYzAbCdEfGhIjK",
"amount_cents": 34900,
"currency": "usd",
"reason": "duplicate",
"customer_id": "cus_QaAbCdEfGhIjK"
},
"justification": "Customer provided proof of duplicate charge within dispute window."
}Sample Cheqpoint response
json
{
"status": "approved",
"modifiedDetails": {
"amount_cents": 17450
},
"decisionNote": "Approved partial refund only — 50% per policy for this dispute reason."
}Node.js — requestSync() before Stripe refund
javascript
import Stripe from "stripe";
import { CheqpointClient } from "@cheqpoint/sdk";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const cheq = new CheqpointClient({ apiKey: process.env.CHEQPOINT_CONNECTION_KEY! });
async function issueAIRefund(chargeId: string, amountCents: number, reason: string) {
const result = await cheq.requestSync({
action: "issue_refund",
summary: `AI agent requesting refund for charge ${chargeId}`,
details: { charge_id: chargeId, amount_cents: amountCents, reason },
timeoutMs: 60_000,
});
if (result.status === "approved") {
// Use modified amount if reviewer changed it
const effectiveAmount = result.modifiedDetails?.amount_cents ?? amountCents;
return await stripe.refunds.create({
charge: chargeId,
amount: effectiveAmount as number,
reason: reason as Stripe.RefundCreateParams.Reason,
});
}
if (result.status === "rejected") {
throw new Error(`Refund rejected: ${result.decisionNote ?? "no reason given"}`);
}
// status === "pending" — decision still awaiting
return { status: "pending", approvalId: result.approvalId };
}Async pattern with callbackUrl
javascript
// For high-volume or time-sensitive payment flows, fire-and-forget:
const result = await cheq.requestAsync({
action: "issue_refund",
summary: `AI agent requesting refund for charge ${chargeId}`,
details: { charge_id: chargeId, amount_cents: amountCents },
// Cheqpoint will POST the final decision here when a reviewer decides:
callbackUrl: "https://api.yourapp.com/webhooks/cheqpoint-decision",
});
// result.status === "pending" → queued for review
// result.status === "approved" → auto-approved by a rule (no human wait)
// result.approvalId → use for trackingNotes
Always prefer modifiedDetails over the original payload — reviewers may adjust refund amounts, currency, or reason codes before approving.
Tips
Gate all AI-initiated financial operations, but allow read-only Stripe queries (balance, charge lookup) to pass through without review.
Get your Connection Key at cheqpoint.co/signup.