Convex Billing
ConvexOfficialPublished by Convex
- Skill
- Tool integration
- Software development
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to integrating Stripe payments into a Convex application. It leverages the @convex-dev/stripe component to handle the complexities of checkout sessions, webhook signature verification, and subscription state management. By following this guide, developers can securely gate application features based on server-side subscription status, ensuring a reliable billing workflow within the Convex ecosystem.
What it does
- Installs and configures the @convex-dev/stripe component.
- Sets up secure webhook routes for Stripe event handling.
- Manages customer creation and checkout session generation.
- Implements server-side gating to verify user subscription status.
- Automates webhook signature verification via the component.
- Provides patterns for storing and retrieving subscription data.
When to use it
- When you need to add subscription-based billing to a Convex app.
- When you want to avoid writing custom Stripe webhook signature verification logic.
- When you need to gate application features based on active subscription status.
- When you are using Convex and want to follow official component integration patterns.
Advantages
- Reduces boilerplate by using a pre-built component for Stripe integration.
- Ensures secure webhook handling with built-in signature verification.
- Centralizes subscription state management within Convex tables.
- Simplifies the developer experience for managing Stripe keys and environment variables.
Usage examples
- “How do I set up Stripe checkout in my Convex project?”
- The agent will guide you through installing @convex-dev/stripe, configuring the component in convex.config.ts, and implementing a checkout action in your backend.
- “How can I check if a user has an active subscription in Convex?”
- The agent will provide a query implementation that uses the component's subscription state to return a boolean status for the authenticated user.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/convex/convex-billing/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip convex-billing.zip -d .agents/skills
Documentation by Convex
<!-- GENERATED from convex-agents content/capabilities/billing.json — do not edit by hand. -->
Add billing / payments
Wire Stripe to Convex using @convex-dev/stripe: a checkout action, an httpAction webhook registered by the component (signature-verified automatically), subscription state stored in the component's tables, and server-side gating via a query.
Workflow
Install the component:
npm install @convex-dev/stripe.Create
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;Store Stripe keys in Convex env (use the
envmicro power):STRIPE_SECRET_KEY(sk_test_… / sk_live_…) andSTRIPE_WEBHOOK_SECRET(whsec_…).Create
convex/http.tsto register the webhook route (the component handles signature verification automatically):import { httpRouter } from 'convex/server'; import { components } from './_generated/api'; import { registerRoutes } from '@convex-dev/stripe'; const http = httpRouter(); registerRoutes(http, components.stripe, { webhookPath: '/stripe/webhook' }); export default http;Create
convex/billing.tswith a checkout action and a subscription-gate query:import { action, query } 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, {}); 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'); 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: 'subscription', successUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?success=true`, cancelUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?canceled=true`, subscriptionMetadata: { userId: identity.subject } }); }, }); export const isSubscribed = query({ args: {}, returns: v.boolean(), handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) return false; const subscriptions = await ctx.runQuery(components.stripe.public.listSubscriptionsByUserId, { userId: identity.subject }); return subscriptions.some((sub) => sub.status === 'active' || sub.status === 'trialing'); }, });Run
npx convex dev --once— it will install the component and push the functions. Verify output shows✔ Installed component stripe.In Stripe Dashboard → Webhooks: add endpoint
https://<deployment>.convex.site/stripe/webhook, subscribe tocheckout.session.completed,customer.subscription.*,invoice.*,payment_intent.*. Copy the signing secret asSTRIPE_WEBHOOK_SECRET.
Rules
Use @convex-dev/stripe (npm: @convex-dev/stripe@^0.1.4) — it handles webhook signature verification internally via registerRoutes; do NOT write a manual constructEvent webhook.
Stripe keys live in Convex env (use the
envmicro power): STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.Gate on server-stored subscription state via isSubscribed query (reads component tables), not client claims.
convex/convex.config.ts must import from '@convex-dev/stripe/convex.config.js' (not .ts) — the .js extension is required by the Convex bundler.
Files
- ATTRIBUTION.mdAdded by AutoGineer852 B
- LICENSELicence file added by AutoGineer10.7 KiB
- SKILL.md3.9 KiB
SKILL.md
<!-- GENERATED from convex-agents content/capabilities/billing.json — do not edit by hand. -->
Add billing / payments
Wire Stripe to Convex using @convex-dev/stripe: a checkout action, an httpAction webhook registered by the component (signature-verified automatically), subscription state stored in the component's tables, and server-side gating via a query.
Workflow
Install the component:
npm install @convex-dev/stripe.Create
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;Store Stripe keys in Convex env (use the
envmicro power):STRIPE_SECRET_KEY(sk_test_… / sk_live_…) andSTRIPE_WEBHOOK_SECRET(whsec_…).Create
convex/http.tsto register the webhook route (the component handles signature verification automatically):import { httpRouter } from 'convex/server'; import { components } from './_generated/api'; import { registerRoutes } from '@convex-dev/stripe'; const http = httpRouter(); registerRoutes(http, components.stripe, { webhookPath: '/stripe/webhook' }); export default http;Create
convex/billing.tswith a checkout action and a subscription-gate query:import { action, query } 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, {}); 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'); 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: 'subscription', successUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?success=true`, cancelUrl: `${process.env.SITE_URL ?? 'http://localhost:3000'}/?canceled=true`, subscriptionMetadata: { userId: identity.subject } }); }, }); export const isSubscribed = query({ args: {}, returns: v.boolean(), handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) return false; const subscriptions = await ctx.runQuery(components.stripe.public.listSubscriptionsByUserId, { userId: identity.subject }); return subscriptions.some((sub) => sub.status === 'active' || sub.status === 'trialing'); }, });Run
npx convex dev --once— it will install the component and push the functions. Verify output shows✔ Installed component stripe.In Stripe Dashboard → Webhooks: add endpoint
https://<deployment>.convex.site/stripe/webhook, subscribe tocheckout.session.completed,customer.subscription.*,invoice.*,payment_intent.*. Copy the signing secret asSTRIPE_WEBHOOK_SECRET.
Rules
Use @convex-dev/stripe (npm: @convex-dev/stripe@^0.1.4) — it handles webhook signature verification internally via registerRoutes; do NOT write a manual constructEvent webhook.
Stripe keys live in Convex env (use the
envmicro power): STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.Gate on server-stored subscription state via isSubscribed query (reads component tables), not client claims.
convex/convex.config.ts must import from '@convex-dev/stripe/convex.config.js' (not .ts) — the .js extension is required by the Convex bundler.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Convex
- Publisher
- Convex (Official)
- Source
- convex/agent-skills · skills/convex-billing · commit f60629d
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Convex or Convex.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download convex-billing.zip