# Table of Contents - [Stripe](#stripe) - [Stripe Starter](#stripe-starter) --- # Stripe [](https://www.convex.dev/) [](https://www.convex.dev/) Product [RealtimeKeep your app up to date](https://www.convex.dev/realtime) [AuthenticationOver 80+ OAuth integrations](https://www.convex.dev/auth) [![Convex Components](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FcomponentsIcon.88c73aa0.svg&w=48&q=75)\ \ ComponentsIndependent, modular, TypeScript building blocks for your backend.](https://www.convex.dev/components) [Open sourceSelf host and develop locally](https://www.convex.dev/open-source) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsparkle.b34d0032.svg&w=48&q=75)\ \ AI CodingGenerate high quality Convex code with AI](https://www.convex.dev/ai) Compare [Convex vs. Firebase](https://www.convex.dev/compare/firebase) [Convex vs. Supabase](https://www.convex.dev/compare/supabase) [Convex vs. SQL](https://www.convex.dev/compare/sql) Developers [DocumentationGet started with your favorite frameworks](https://docs.convex.dev/) [SearchSearch across Docs, Stack, and Discord](https://search.convex.dev/) [TemplatesUse a recipe to get started quickly](https://www.convex.dev/templates) [Convex for StartupsStart and scale your company with Convex](https://www.convex.dev/startups) [Convex ChampionsAmbassadors that support our thriving community](https://www.convex.dev/champions) [Convex CommunityShare ideas and ask for help in our community Discord](https://www.convex.dev/community) [![Stack](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FstackColor.52088746.svg&w=32&q=75)\ \ Stack\ \ Stack is the Convex developer portal and blog, sharing bright ideas and techniques for building with Convex.\ \ Explore Stack](https://stack.convex.dev/) [Blog](https://stack.convex.dev/) [Docs](https://docs.convex.dev/) [Pricing](https://www.convex.dev/pricing) [GitHub](https://github.com/get-convex/convex-backend) [Log in](https://www.convex.dev/login) [Start building](https://www.convex.dev/start) [Back to Components](https://www.convex.dev/components) Stripe ====== [![get-convex's avatar](https://www.convex.dev/_next/image?url=https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F81530787%3Fv%3D4&w=96&q=75)\ \ get-convex/stripe\ \ View repo](https://github.com/get-convex/stripe) [![GitHub logo](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fnpm.bd053a67.svg&w=48&q=75)View package](https://www.npmjs.com/package/@convex-dev/stripe) ### Category [Payments](https://www.convex.dev/components#payments "Show all components in "Payments" category") ![Stripe hero image](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fstripe.ebb6b11d.png&w=1536&q=75) npm install @convex-dev/stripe @convex-dev/stripe ================== A Convex component for integrating Stripe payments, subscriptions, and billing into your Convex application. [![npm version](https://badge.fury.io/js/@convex-dev%2Fstripe.svg)](https://badge.fury.io/js/@convex-dev%2Fstripe) Features[#](https://www.convex.dev/components/stripe#features) --------------------------------------------------------------- * 🛒 **Checkout Sessions** - Create one-time payment and subscription checkouts * 📦 **Subscription Management** - Create, update, cancel subscriptions * 👥 **Customer Management** - Automatic customer creation and linking * 💳 **Customer Portal** - Let users manage their billing * 🪑 **Seat-Based Pricing** - Update subscription quantities for team billing * 🔗 **User/Org Linking** - Link payments and subscriptions to users or organizations * 🔔 **Webhook Handling** - Automatic sync of Stripe data to your Convex database * 📊 **Real-time Data** - Query payments, subscriptions, invoices in real-time Quick Start[#](https://www.convex.dev/components/stripe#quick-start) --------------------------------------------------------------------- ### 1\. Install the Component[#](https://www.convex.dev/components/stripe#1-install-the-component) npm install @convex-dev/stripe ### 2\. Add to Your Convex App[#](https://www.convex.dev/components/stripe#2-add-to-your-convex-app) Create or update `convex/convex.config.ts`: import { defineApp } from "convex/server"; import stripe from "@convex-dev/stripe/convex.config.js"; const app = defineApp(); app.use(stripe); export default app; ### 3\. Set Up Environment Variables[#](https://www.convex.dev/components/stripe#3-set-up-environment-variables) Add these to your [Convex Dashboard](https://dashboard.convex.dev/) → Settings → Environment Variables: | Variable | Description | | --- | --- | | `STRIPE_SECRET_KEY` | Your Stripe secret key (`sk_test_...` or `sk_live_...`) | | `STRIPE_WEBHOOK_SECRET` | Webhook signing secret (`whsec_...`) - see Step 4 | ### 4\. Configure Stripe Webhooks[#](https://www.convex.dev/components/stripe#4-configure-stripe-webhooks) 1. Go to [Stripe Dashboard → Developers → Webhooks](https://dashboard.stripe.com/test/webhooks) 2. Click **"Add endpoint"** 3. Enter your webhook URL: https://.convex.site/stripe/webhook (Find your deployment name in the Convex dashboard - it's the part before `.convex.cloud` in your URL) 4. Select these events: * `checkout.session.completed` * `customer.created` * `customer.updated` * `customer.subscription.created` * `customer.subscription.updated` * `customer.subscription.deleted` * `invoice.created` * `invoice.finalized` * `invoice.paid` * `invoice.payment_failed` * `payment_intent.succeeded` * `payment_intent.payment_failed` 5. Click **"Add endpoint"** 6. Copy the **Signing secret** and add it as `STRIPE_WEBHOOK_SECRET` in Convex ### 5\. Register Webhook Routes[#](https://www.convex.dev/components/stripe#5-register-webhook-routes) Create `convex/http.ts`: import { httpRouter } from "convex/server"; import { components } from "./_generated/api"; import { registerRoutes } from "@convex-dev/stripe"; const http = httpRouter(); // Register Stripe webhook handler at /stripe/webhook registerRoutes(http, components.stripe, { webhookPath: "/stripe/webhook", }); export default http; ### 6\. Use the Component[#](https://www.convex.dev/components/stripe#6-use-the-component) Create `convex/stripe.ts`: import { action } from "./_generated/server"; import { components } from "./_generated/api"; import { StripeSubscriptions } from "@convex-dev/stripe"; import { v } from "convex/values"; const stripeClient = new StripeSubscriptions(components.stripe, {}); // Create a checkout session for a subscription export const createSubscriptionCheckout = action({ args: { priceId: v.string() }, returns: v.object({ sessionId: v.string(), url: v.union(v.string(), v.null()), }), handler: async (ctx, args) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) throw new Error("Not authenticated"); // Get or create a Stripe customer const customer = await stripeClient.getOrCreateCustomer(ctx, { userId: identity.subject, email: identity.email, name: identity.name, }); // Create checkout session return await stripeClient.createCheckoutSession(ctx, { priceId: args.priceId, customerId: customer.customerId, mode: "subscription", successUrl: "http://localhost:5173/?success=true", cancelUrl: "http://localhost:5173/?canceled=true", subscriptionMetadata: { userId: identity.subject }, }); }, }); // Create a checkout session for a one-time payment export const createPaymentCheckout = action({ args: { priceId: v.string() }, returns: v.object({ sessionId: v.string(), url: v.union(v.string(), v.null()), }), handler: async (ctx, args) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) throw new Error("Not authenticated"); const customer = await stripeClient.getOrCreateCustomer(ctx, { userId: identity.subject, email: identity.email, name: identity.name, }); return await stripeClient.createCheckoutSession(ctx, { priceId: args.priceId, customerId: customer.customerId, mode: "payment", successUrl: "http://localhost:5173/?success=true", cancelUrl: "http://localhost:5173/?canceled=true", paymentIntentMetadata: { userId: identity.subject }, }); }, }); API Reference[#](https://www.convex.dev/components/stripe#api-reference) ------------------------------------------------------------------------- ### StripeSubscriptions Client[#](https://www.convex.dev/components/stripe#stripesubscriptions-client) import { StripeSubscriptions } from "@convex-dev/stripe"; const stripeClient = new StripeSubscriptions(components.stripe, { STRIPE_SECRET_KEY: "sk_...", // Optional, defaults to process.env.STRIPE_SECRET_KEY }); #### Methods[#](https://www.convex.dev/components/stripe#methods) | Method | Description | | --- | --- | | `createCheckoutSession()` | Create a Stripe Checkout session | | `createCustomerPortalSession()` | Generate a Customer Portal URL | | `createCustomer()` | Create a new Stripe customer | | `getOrCreateCustomer()` | Get existing or create new customer | | `cancelSubscription()` | Cancel a subscription | | `reactivateSubscription()` | Reactivate a subscription set to cancel | | `updateSubscriptionQuantity()` | Update seat count | ### createCheckoutSession[#](https://www.convex.dev/components/stripe#createcheckoutsession) await stripeClient.createCheckoutSession(ctx, { priceId: "price_...", customerId: "cus_...", // Optional mode: "subscription", // "subscription" | "payment" | "setup" successUrl: "https://...", cancelUrl: "https://...", quantity: 1, // Optional, default 1 metadata: {}, // Optional, session metadata subscriptionMetadata: {}, // Optional, attached to subscription paymentIntentMetadata: {}, // Optional, attached to payment intent }); ### Component Queries[#](https://www.convex.dev/components/stripe#component-queries) Access data directly via the component's public queries: import { query } from "./_generated/server"; import { components } from "./_generated/api"; // List subscriptions for a user export const getUserSubscriptions = query({ args: {}, handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) return []; return await ctx.runQuery( components.stripe.public.listSubscriptionsByUserId, { userId: identity.subject }, ); }, }); // List payments for a user export const getUserPayments = query({ args: {}, handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) return []; return await ctx.runQuery(components.stripe.public.listPaymentsByUserId, { userId: identity.subject, }); }, }); ### Available Public Queries[#](https://www.convex.dev/components/stripe#available-public-queries) | Query | Arguments | Description | | --- | --- | --- | | `getCustomer` | `stripeCustomerId` | Get a customer by Stripe ID | | `listSubscriptions` | `stripeCustomerId` | List subscriptions for a customer | | `listSubscriptionsByUserId` | `userId` | List subscriptions for a user | | `getSubscription` | `stripeSubscriptionId` | Get a subscription by ID | | `getSubscriptionByOrgId` | `orgId` | Get subscription for an org | | `getPayment` | `stripePaymentIntentId` | Get a payment by ID | | `listPayments` | `stripeCustomerId` | List payments for a customer | | `listPaymentsByUserId` | `userId` | List payments for a user | | `listPaymentsByOrgId` | `orgId` | List payments for an org | | `listInvoices` | `stripeCustomerId` | List invoices for a customer | | `listInvoicesByUserId` | `userId` | List invoices for a user | | `listInvoicesByOrgId` | `orgId` | List invoices for an org | Webhook Events[#](https://www.convex.dev/components/stripe#webhook-events) --------------------------------------------------------------------------- The component automatically handles these Stripe webhook events: | Event | Action | | --- | --- | | `customer.created` | Creates customer record | | `customer.updated` | Updates customer record | | `customer.subscription.created` | Creates subscription record | | `customer.subscription.updated` | Updates subscription record | | `customer.subscription.deleted` | Marks subscription as canceled | | `payment_intent.succeeded` | Creates payment record | | `payment_intent.payment_failed` | Updates payment status | | `invoice.created` | Creates invoice record | | `invoice.paid` | Updates invoice to paid | | `invoice.payment_failed` | Marks invoice as failed | | `checkout.session.completed` | Handles completed checkout sessions | ### Custom Webhook Handlers[#](https://www.convex.dev/components/stripe#custom-webhook-handlers) Add custom logic to webhook events: import { httpRouter } from "convex/server"; import { components } from "./_generated/api"; import { registerRoutes } from "@convex-dev/stripe"; import type Stripe from "stripe"; const http = httpRouter(); registerRoutes(http, components.stripe, { events: { "customer.subscription.updated": async (ctx, event: Stripe.CustomerSubscriptionUpdatedEvent) => { const subscription = event.data.object; console.log("Subscription updated:", subscription.id, subscription.status); // Add custom logic here }, }, onEvent: async (ctx, event: Stripe.Event) => { // Called for ALL events - useful for logging/analytics console.log("Stripe event:", event.type); }, }); export default http; Database Schema[#](https://www.convex.dev/components/stripe#database-schema) ----------------------------------------------------------------------------- The component creates these tables in its namespace: ### customers[#](https://www.convex.dev/components/stripe#customers) | Field | Type | Description | | --- | --- | --- | | `stripeCustomerId` | string | Stripe customer ID | | `email` | string? | Customer email | | `name` | string? | Customer name | | `metadata` | object? | Custom metadata | ### subscriptions[#](https://www.convex.dev/components/stripe#subscriptions) | Field | Type | Description | | --- | --- | --- | | `stripeSubscriptionId` | string | Stripe subscription ID | | `stripeCustomerId` | string | Customer ID | | `status` | string | Subscription status | | `priceId` | string | Price ID | | `quantity` | number? | Seat count | | `currentPeriodEnd` | number | Period end timestamp | | `cancelAtPeriodEnd` | boolean | Will cancel at period end | | `userId` | string? | Linked user ID | | `orgId` | string? | Linked org ID | | `metadata` | object? | Custom metadata | ### checkout\_sessions[#](https://www.convex.dev/components/stripe#checkoutsessions) | Field | Type | Description | | --- | --- | --- | | `stripeCheckoutSessionId` | string | Checkout session ID | | `stripeCustomerId` | string? | Customer ID | | `status` | string | Session status | | `mode` | string | Session mode (payment/subscription/setup) | | `metadata` | object? | Custom metadata | ### payments[#](https://www.convex.dev/components/stripe#payments) | Field | Type | Description | | --- | --- | --- | | `stripePaymentIntentId` | string | Payment intent ID | | `stripeCustomerId` | string? | Customer ID | | `amount` | number | Amount in cents | | `currency` | string | Currency code | | `status` | string | Payment status | | `created` | number | Created timestamp | | `userId` | string? | Linked user ID | | `orgId` | string? | Linked org ID | | `metadata` | object? | Custom metadata | ### invoices[#](https://www.convex.dev/components/stripe#invoices) | Field | Type | Description | | --- | --- | --- | | `stripeInvoiceId` | string | Invoice ID | | `stripeCustomerId` | string | Customer ID | | `stripeSubscriptionId` | string? | Subscription ID | | `status` | string | Invoice status | | `amountDue` | number | Amount due | | `amountPaid` | number | Amount paid | | `created` | number | Created timestamp | | `userId` | string? | Linked user ID | | `orgId` | string? | Linked org ID | Example App[#](https://www.convex.dev/components/stripe#example-app) --------------------------------------------------------------------- Check out the full example app in the [`example/`](https://github.com/get-convex/stripe/blob/master/example) directory: git clone https://github.com/get-convex/convex-stripe cd convex-stripe npm install npm run dev The example includes: * Landing page with product showcase * One-time payments and subscriptions * User profile with order history * Subscription management (cancel, update seats) * Customer portal integration * Team/organization billing Authentication[#](https://www.convex.dev/components/stripe#authentication) --------------------------------------------------------------------------- This component works with any Convex authentication provider. The example uses [Clerk](https://clerk.com/) : 1. Create a Clerk application at [clerk.com](https://clerk.com/) 2. Add `VITE_CLERK_PUBLISHABLE_KEY` to your `.env.local` 3. Create `convex/auth.config.ts`: export default { providers: [\ {\ domain: "https://your-clerk-domain.clerk.accounts.dev",\ applicationID: "convex",\ },\ ], }; Troubleshooting[#](https://www.convex.dev/components/stripe#troubleshooting) ----------------------------------------------------------------------------- ### Tables are empty after checkout[#](https://www.convex.dev/components/stripe#tables-are-empty-after-checkout) Make sure you've: 1. Set `STRIPE_SECRET_KEY` and `STRIPE_WEBHOOK_SECRET` in Convex environment variables 2. Configured the webhook endpoint in Stripe with the correct events 3. Added `invoice.created` and `invoice.finalized` events (not just `invoice.paid`) ### "Not authenticated" errors[#](https://www.convex.dev/components/stripe#not-authenticated-errors) Ensure your auth provider is configured: 1. Create `convex/auth.config.ts` with your provider 2. Run `npx convex dev` to push the config 3. Verify the user is signed in before calling actions ### Webhooks returning 400/500[#](https://www.convex.dev/components/stripe#webhooks-returning-400500) Check the Convex logs in your dashboard for errors. Common issues: * Missing `STRIPE_WEBHOOK_SECRET` * Wrong webhook URL (should be `https://.convex.site/stripe/webhook`) * Missing events in webhook configuration License[#](https://www.convex.dev/components/stripe#license) ------------------------------------------------------------- Apache-2.0 Get your app up and running in minutes [Start building](https://www.convex.dev/start) ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-cruiser.9b0dabcf.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-frame.c16770b0.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-kernel.48322c09.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-portal.4d4967d3.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-burst.811fff05.svg&w=256&q=75) [![Convex logo](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.46ec36bd.svg&w=256&q=75)](https://www.convex.dev/) Product[Sync](https://www.convex.dev/sync) [Realtime](https://www.convex.dev/realtime) [Auth](https://www.convex.dev/auth) [Open source](https://www.convex.dev/open-source) [AI coding](https://www.convex.dev/ai) [Chef](https://chef.convex.dev/) [FAQ](https://www.convex.dev/faq) [Pricing](https://www.convex.dev/pricing) Developers[Docs](https://docs.convex.dev/) [Blog](https://stack.convex.dev/) [Components](https://www.convex.dev/components) [Templates](https://www.convex.dev/templates) [Startups](https://www.convex.dev/startups) [Champions](https://www.convex.dev/champions) [Changelog](https://www.convex.dev/releases) [Podcast](https://www.convex.dev/podcast) [LLMs.txt](https://docs.convex.dev/llms.txt) Company[About us](https://www.convex.dev/about-us) [Brand](https://www.convex.dev/brand) [Investors](https://www.convex.dev/investors) [Become a partner](https://www.convex.dev/partners/apply) [Jobs](https://www.convex.dev/jobs) [News](https://news.convex.dev/) [Events](https://www.convex.dev/events) [Terms of service](https://www.convex.dev/legal/tos) [Privacy policy](https://www.convex.dev/legal/privacy) [Security](https://www.convex.dev/security) Social[![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftwitter.3de2e5aa.svg&w=48&q=75)Twitter](https://x.com/convex) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdiscord.ef0a3bd8.svg&w=48&q=75)Discord](https://www.convex.dev/community) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fyoutube.c04dcde7.svg&w=48&q=75)YouTube](https://www.youtube.com/@convex-dev) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fluma.7e8c0688.svg&w=48&q=75)Luma](https://lu.ma/convex) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flinkedin.8e8bbdc2.svg&w=48&q=75)LinkedIn](https://www.linkedin.com/company/convex-dev) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fgithub.d634168b.svg&w=48&q=75)GitHub](https://github.com/get-convex) A Trusted Solution * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**SOC 2** Type II Compliant * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**HIPAA** Compliant * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**GDPR** Verified ©2025 Convex, Inc. --- # Stripe Starter [](https://www.convex.dev/) [](https://www.convex.dev/) Product [RealtimeKeep your app up to date](https://www.convex.dev/realtime) [AuthenticationOver 80+ OAuth integrations](https://www.convex.dev/auth) [![Convex Components](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FcomponentsIcon.88c73aa0.svg&w=48&q=75)\ \ ComponentsIndependent, modular, TypeScript building blocks for your backend.](https://www.convex.dev/components) [Open sourceSelf host and develop locally](https://www.convex.dev/open-source) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsparkle.b34d0032.svg&w=48&q=75)\ \ AI CodingGenerate high quality Convex code with AI](https://www.convex.dev/ai) Compare [Convex vs. Firebase](https://www.convex.dev/compare/firebase) [Convex vs. Supabase](https://www.convex.dev/compare/supabase) [Convex vs. SQL](https://www.convex.dev/compare/sql) Developers [DocumentationGet started with your favorite frameworks](https://docs.convex.dev/) [SearchSearch across Docs, Stack, and Discord](https://search.convex.dev/) [TemplatesUse a recipe to get started quickly](https://www.convex.dev/templates) [Convex for StartupsStart and scale your company with Convex](https://www.convex.dev/startups) [Convex ChampionsAmbassadors that support our thriving community](https://www.convex.dev/champions) [Convex CommunityShare ideas and ask for help in our community Discord](https://www.convex.dev/community) [![Stack](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FstackColor.52088746.svg&w=32&q=75)\ \ Stack\ \ Stack is the Convex developer portal and blog, sharing bright ideas and techniques for building with Convex.\ \ Explore Stack](https://stack.convex.dev/) [Blog](https://stack.convex.dev/) [Docs](https://docs.convex.dev/) [Pricing](https://www.convex.dev/pricing) [GitHub](https://github.com/get-convex/convex-backend) [Log in](https://www.convex.dev/login) [Start building](https://www.convex.dev/start) [Back to Templates](https://www.convex.dev/templates) Stripe Starter ============== [![GitHub logo](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fgithub.2fd3e44b.svg&w=48&q=75)View Repo](https://github.com/get-convex/convex-stripe-demo) [View Live](https://xixixao.github.io/paymorebeseen/) ### Built with [![Stripe icon](https://www.convex.dev/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F720c153a0ec04caea201987f8294d4c5f491a5e6-800x800.svg%3Fdpr%3D2%26fm%3Dpng&w=1536&q=75 "Stripe")Stripe](https://stripe.com/) ### Tags [Starter](https://www.convex.dev/templates?tags=Starter "Show all templates tagged "Starter"") `npx create-convex@latest -t get-convex/convex-stripe-demo` This example app demonstrates how to integrate Stripe, the payments platform, with Convex, the backend application platform. We keep track of payments in Convex and fulfill orders when they're confirmed by Stripe. You can test the payment flow end to end using Stripe's test card numbersTo test the payments flow, follow these steps: 1. Sign up for Stripe for free at [https://stripe.com/](https://stripe.com/) 2. [Install the stripe CLI](https://stripe.com/docs/stripe-cli) 3. Run`stripe listen --forward-to localhost:5173/stripe` 4. Copy the "Your webhook signing secret" from the output of the `listen` command, and set it as `STRIPE_WEBHOOKS_SECRET` environment variable on your Convex dashboard 5. Copy your test secret API key from the code example on [https://stripe.com/docs/checkout/quickstart](https://stripe.com/docs/checkout/quickstart) and set it as `STRIPE_KEY` environment variable on your Convex dashboard You can then use the test credit card details to go through the payment flow, see [https://stripe.com/docs/checkout/quickstart#testing](https://stripe.com/docs/checkout/quickstart#testing) ![Stripe Starter hero image](https://www.convex.dev/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F97b28bec28caa96cbf88c99ff0355cbe22c4e6af-2400x1256.png%3Ffit%3Dcrop%26w%3D1200%26h%3D675&w=1536&q=75) ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fflair.3fae67ce.svg&w=96&q=75) Get your app up and running in minutes [Start building](https://www.convex.dev/start) ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-cruiser.9b0dabcf.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-frame.c16770b0.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-kernel.48322c09.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-portal.4d4967d3.svg&w=256&q=75)![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fpixel-burst.811fff05.svg&w=256&q=75) [![Convex logo](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.46ec36bd.svg&w=256&q=75)](https://www.convex.dev/) Product[Sync](https://www.convex.dev/sync) [Realtime](https://www.convex.dev/realtime) [Auth](https://www.convex.dev/auth) [Open source](https://www.convex.dev/open-source) [AI coding](https://www.convex.dev/ai) [Chef](https://chef.convex.dev/) [FAQ](https://www.convex.dev/faq) [Pricing](https://www.convex.dev/pricing) Developers[Docs](https://docs.convex.dev/) [Blog](https://stack.convex.dev/) [Components](https://www.convex.dev/components) [Templates](https://www.convex.dev/templates) [Startups](https://www.convex.dev/startups) [Champions](https://www.convex.dev/champions) [Changelog](https://www.convex.dev/releases) [Podcast](https://www.convex.dev/podcast) [LLMs.txt](https://docs.convex.dev/llms.txt) Company[About us](https://www.convex.dev/about-us) [Brand](https://www.convex.dev/brand) [Investors](https://www.convex.dev/investors) [Become a partner](https://www.convex.dev/partners/apply) [Jobs](https://www.convex.dev/jobs) [News](https://news.convex.dev/) [Events](https://www.convex.dev/events) [Terms of service](https://www.convex.dev/legal/tos) [Privacy policy](https://www.convex.dev/legal/privacy) [Security](https://www.convex.dev/security) Social[![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Ftwitter.3de2e5aa.svg&w=48&q=75)Twitter](https://x.com/convex) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdiscord.ef0a3bd8.svg&w=48&q=75)Discord](https://www.convex.dev/community) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fyoutube.c04dcde7.svg&w=48&q=75)YouTube](https://www.youtube.com/@convex-dev) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fluma.7e8c0688.svg&w=48&q=75)Luma](https://lu.ma/convex) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flinkedin.8e8bbdc2.svg&w=48&q=75)LinkedIn](https://www.linkedin.com/company/convex-dev) [![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fgithub.d634168b.svg&w=48&q=75)GitHub](https://github.com/get-convex) A Trusted Solution * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**SOC 2** Type II Compliant * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**HIPAA** Compliant * ![](https://www.convex.dev/_next/image?url=%2F_next%2Fstatic%2Fmedia%2FtrustCheck.d411e2c8.svg&w=48&q=75)**GDPR** Verified ©2025 Convex, Inc. ---