Drop-in Convex component that handles Flutterwave payments, subscriptions, webhook ingestion, and reactive state with zero boilerplate.
npm install convex-flutterwaveconvex-flutterwave integrates Flutterwave's v3 Standard payment API into Convex, handling webhook ingestion, signature verification, and local state persistence so you do not have to build that infrastructure yourself. It exposes reactive queries for transaction and subscription state, server-side verification, plan management, and subscription lifecycle controls. Duplicate webhook deliveries are detected and skipped automatically.
convex-flutterwave provides an initializeTransaction() action that calls Flutterwave's v3 Standard endpoint, records a pending transaction in Convex, and returns a hosted payment link. After the customer pays and is redirected, call verifyTransaction() server-side to confirm the final status. The component handles all database writes so transaction state is immediately available to Convex queries.
convex-flutterwave exposes a webhookHandler that you mount on a Convex HTTP route. It verifies the Flutterwave webhook secret hash, processes charge.completed and subscription.cancelled events, deduplicates repeat deliveries, and writes results to Convex tables. You register the webhook URL in the Flutterwave dashboard once and the component handles everything else.
Create a billing plan with createPaymentPlan() specifying a name, amount, interval, and currency, then pass the returned planId as paymentPlan to initializeTransaction(). After the customer's first successful charge, call syncCustomerSubscriptions() to pull live subscription records from Flutterwave into Convex, since Flutterwave does not emit a subscription created webhook. Use hasActiveSubscription() in any query to check current status.
convex-flutterwave stores every transaction keyed by tx_ref in Convex tables. Use getTransaction() or listTransactions() inside Convex queries to read this state reactively. When a webhook arrives after a payment event, Convex's real-time reactivity propagates the updated status to all subscribed clients instantly without any additional polling logic.
convex-flutterwave uses Flutterwave's v3 Standard integration at api.flutterwave.com/v3, authenticated with a static secret key. It does not use the newer v4 OAuth flow. Flutterwave v3 remains fully supported and is what most existing Flutterwave integrations use.
convex-flutterwave implements webhook idempotency by detecting duplicate event deliveries and skipping them before any database write occurs. This means re-delivered events from Flutterwave will not create duplicate transaction records or trigger duplicate state updates in your Convex deployment.
Yes, but it requires an explicit sync step. Flutterwave does not emit a subscription created event, so convex-flutterwave provides syncCustomerSubscriptions() which calls Flutterwave's List Subscriptions endpoint and upserts the results into Convex. Call this after verifyTransaction() confirms a plan-linked checkout succeeded, and optionally expose it as an on-demand sync action in your UI.
convex-flutterwave requires Convex v1.33.1 or later and Node.js 18 or later. You also need an active Flutterwave account to obtain a secret key and configure the webhook secret hash.
Flutterwave redirects to your redirectUrl with status and tx_ref query parameters on every outcome. When a chargeable attempt was made, transaction_id is also included. Pass transaction_id to verifyTransaction() in a Convex action to confirm the final status directly with Flutterwave. Note that failed or abandoned checkouts redirect without a transaction_id, so your callback route should handle that case explicitly rather than assuming transaction_id is always present.