RevClamp Enterprise B2B REVENUE ASSURANCE Start Free
INTEGRATION GUIDE | STRIPE & POSTHOG SETUP

Stripe App & Multi-Stack Webhook Guard Reference

Connect your product usage stream from PostHog or your backend so RevClamp can automatically stop unpaid usage and prepare Stripe dispute evidence across Next.js, Node.js/Express, and Python/FastAPI.

STEP 0 • WHERE TO GET YOUR CREDENTIALS (30 SECONDS) Open /dashboard Step 1 →

Before dropping the middleware snippet into your app, map these three credentials from your Merchant Console (/dashboard), 2-Min Quickstart (/docs/onboarding), or test ephemerally in /tools/stripe-basil-auditor:

Credential / Env Var Format Where to Obtain It
X-RevClamp-Tenant-Key rg_live_... Your Workspace API Key (rg_live_...) generated in /dashboard Step 1.
REVCLAMP_TENANT_ID tnt_... Your Workspace ID (tnt_...) shown in /dashboard Step 1 & Step 2 (Live Telemetry Synchronized: Workspace tnt_...) or returned when provisioning.
REVCLAMP_WEBHOOK_SECRET whsec_rg_... Your Workspace Webhook Signing Secret (whsec_rg_...) issued alongside your API Key in /dashboard Step 1 (POST /api/dashboard/provision) and used by RevClamp to sign outbound X-RevClamp-Signature headers.
DROP-IN PRODUCTION WEBHOOK ENTITLEMENT GUARD (NEXT.JS / EXPRESS / FASTAPI)
// app/api/webhooks/revclamp/route.ts -- Next.js App Router (TypeScript Edge/Node)
import crypto from "node:crypto";

export async function POST(req: Request) {
  const rawBody = await req.text();
  const payload = JSON.parse(rawBody); // payload.event: "revclamp.entitlement.revoke" | "revclamp.entitlement.restore"
  const [, t = "", v1 = ""] = (req.headers.get("x-revclamp-signature") || "").match(/^t=(\d+),v1=([0-9a-f]{64})$/) || [];
  if (!t || !v1 || Math.abs(Math.floor(Date.now() / 1000) - Number(t)) > 300) return Response.json({ ok: false, error: "INVALID_SIGNATURE" }, { status: 401 });
  if (payload.event !== "revclamp.entitlement.revoke" && payload.event !== "revclamp.entitlement.restore") return Response.json({ ok: false, error: "UNSUPPORTED_EVENT" }, { status: 400 });
  const scope = payload.event === "revclamp.entitlement.restore" ? "revclamp_restore_scope" : "revclamp_revoke_scope";
  if (process.env.REVCLAMP_TENANT_ID && payload.tenant_id !== process.env.REVCLAMP_TENANT_ID) return Response.json({ ok: false, error: "TENANT_MISMATCH" }, { status: 403 });
  const derivedKey = crypto.createHmac("sha256", (process.env.REVCLAMP_WEBHOOK_SECRET || "").trim()).update(JSON.stringify([scope, payload.tenant_id || "default", payload.account_id || "default"])).digest("hex");
  const expectedV1 = crypto.createHmac("sha256", derivedKey).update(t + "." + rawBody, "utf8").digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(v1, "hex"), Buffer.from(expectedV1, "hex"))) return Response.json({ ok: false, error: "INVALID_SIGNATURE" }, { status: 401 });
  await db.tenants.update({ where: { stripeCustomerId: payload.customer_id, transitionSeq: { lt: payload.transition_seq } }, data: { apiAccessPaused: payload.event === "revclamp.entitlement.revoke", transitionSeq: payload.transition_seq } });
  return Response.json({ ok: true, customer_id: payload.customer_id, handled: payload.event });
}
STRIPE DASHBOARD DRAWER & API INTEGRATION
// 1. Check Customer Protection Status (stripe.dashboard.customer.detail)
const cusRes = await fetch(
  "https://api.revclamp.com/v1/stripe/customer-drawer?customer_id=" + encodeURIComponent(customerId),
  { headers: { "X-RevClamp-Tenant-Key": "<YOUR_TENANT_KEY>" } }
);
const { ok: cusOk, drawer: customerDrawer } = await cusRes.json();

// 2. Stage Chargeback Evidence Draft (stripe.dashboard.dispute.detail)
const dispRes = await fetch("https://api.revclamp.com/v1/stripe/dispute-drawer", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-RevClamp-Tenant-Key": "<YOUR_TENANT_KEY>"
  },
  body: JSON.stringify({ existingDispute, expectedCustomerId: customerId, usageEvents })
});
const { ok: dispOk, drawer: disputeDrawer } = await dispRes.json();

Zero-Risk & Fail-Open CTO Architecture Guarantees

Engineering SafeguardRuntime Guarantee
Out-of-Band Enforcement (Fail-Open)Entitlement lock/restore signals arrive via signed webhooks (crypto.timingSafeEqual) and never block your live customer API request path.
Stateless Ephemeral Read-Only Audit1-click historical readiness audits (POST /api/dashboard/readiness-audit) evaluate caller-supplied customers and usageEvents ephemerally in memory (statelessEphemeralAudit: true) when custom payloads are passed, without persisting raw Stripe customer lists.
No Raw Prompts or Card Payloads StoredIngests strictly quantitative usage metadata (stripe_customer_id, event_name, units, occurredAtSec).
Non-Destructive submit: false StagingAppends verified activity inside [RevClamp Verified Product Usage Log] delimiters without overwriting merchant notes or auto-submitting to card networks.

PostHog Webhook Settings (Zero-Code)

SettingValue to Enter
Webhook Destination URLhttps://api.revclamp.com/v1/events/ingest
HTTP MethodPOST
Authentication HeaderX-RevClamp-Tenant-Key: <YOUR_TENANT_KEY>
Customer MatchingMatches stripe_customer_id first, or falls back to verified customer email
EU Cookieless Privacy ModeFully compatible with PostHog $ip: null (no cookies required)

Automatic Stripe Events Handled by RevClamp

Stripe Webhook EventHow RevClamp Protects You
customer.subscription.updatedSyncs plan upgrades, renewals, and status changes in real time
customer.subscription.deletedMonitors post-cancellation usage and locks unpaid accounts after your grace period
invoice.payment_failedStarts your custom payment-retry grace window before restricting access
charge.dispute.createdAutomatically compiles 90 days of customer usage proof into a Stripe Dispute draft