Preface

Once a SaaS or content site decides to charge fees, it typically needs to handle checkout pages, one-time payments or subscriptions, permission activation after successful payment, and users’ ability to modify their plans or cancel subscriptions themselves. Stripe is one of the most common solutions for overseas projects, but its official documentation covers multiple sections including Checkout Session, webhook signature verification, Billing Portal, price catalogs, and more. Missing signature verification, hardcoding secrets in frontend code, or failing to test webhooks locally are all frequent integration pitfalls.

adding-stripe is a workflow instruction from the community-curated Skill list awesome-cursor-skills, which breaks down “adding Stripe to a web application” into a reusable SKILL.md file. When you use tools that support Agent Skills like Cursor, Claude Code, or Codex CLI and say “add payments”, “build subscriptions”, or “integrate Stripe”, the Agent will follow this 7-step checklist instead of piecing together documentation from scratch.

What is this

adding-stripe is an Agent Skill configuration file maintained at spencerpauly/awesome-cursor-skills/resources/adding-stripe, curated and included by the community and not officially produced by Stripe. The repository’s README categorizes it under the Authentication & Payments section, with a one-sentence description: Integrate Stripe checkout, subscriptions, webhooks, and customer portal.

The YAML description in SKILL.md reads: Integrate Stripe payments into a web application, including checkout sessions, webhooks, and customer portal. The trigger conditions are clearly defined: it activates when the user mentions payments, billing, subscriptions, or Stripe integration.

It falls into the category of “translating common official integration paths into an executable checklist for Agents”: it depends on stripe and @stripe/stripe-js, uses Checkout Session for hosted checkout, uses webhooks to synchronize subscription status, and optionally integrates the Customer Portal. The example paths (lib/stripe.ts, NEXT_PUBLIC_*, localhost:3000) are clearly targeted at Node.js web applications like Next.js, rather than a full custom Payment Element or Stripe Connect solution.

Core Features and Highlights

Based on the original Skill text and cross-checked with the Stripe Checkout Session API, webhook documentation, and Customer Portal integration guide, this checklist covers the following tasks.

  1. Install server-side and browser SDKs
    npm install stripe @stripe/stripe-js. stripe is the official Node.js library (stripe-node) responsible for secrets, Checkout, webhooks, and Portal; @stripe/stripe-js is the official Stripe.js loading tool, which uses loadStripe on the client to retrieve the publishable key.

  2. Environment Variables
    The Skill requires configuring STRIPE_SECRET_KEY, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, and STRIPE_WEBHOOK_SECRET, with example values sk_test_..., pk_test_..., and whsec_... respectively. The NEXT_PUBLIC_ prefix indicates that the publishable key can be exposed to Next.js clients; secrets (sk_, whsec_) must only be stored on the server.

  3. Centralized Stripe Client Initialization
    Instantiate the client in lib/stripe.ts using STRIPE_SECRET_KEY:

   import Stripe from "stripe";

   export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
     apiVersion: "2024-12-18.acacia",
   });

2024-12-18.acacia is a valid Stripe API version (Acacia). Note that as of August 2026, newer versions of stripe-node default to a newer API version (for example, 2026-07-29.dahlia). The Skill hardcodes Acacia, and Agents may copy it verbatim; when upgrading the SDK, refer to the Stripe upgrade guide and the current stripe package instead of using unchecked type definitions.

  1. Create a Checkout Session
    The core call given in the Skill is stripe.checkout.sessions.create: the mode can be "subscription" or one-time "payment"; line_items uses the Price ID; success_url includes the official placeholder {CHECKOUT_SESSION_ID} (Stripe will replace it with the real Session ID); use cancel_url for failed payments. After successful creation, redirect to session.url, which is the Stripe-hosted checkout page.

  2. Handle Subscription Lifecycle with Webhooks
    In POST /api/webhooks/stripe, use stripe.webhooks.constructEvent to verify signatures, and handle events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed, then write the subscription status back to your own database. This aligns with Stripe’s recommended events for subscription and portal scenarios.

  3. Optional Customer Portal
    Add an endpoint that calls stripe.billingPortal.sessions.create and redirects the user to Stripe’s billing portal, allowing them to manage their own subscriptions. Stripe’s documentation confirms that you must first configure portal features in the Dashboard, and typically pass customer and return_url when creating a Session.

  4. Pricing Page UI
    Build a set of plan cards that call the Checkout API when clicked. The Skill also recommends dynamically fetching prices using stripe.prices.list instead of hardcoding Price IDs in the frontend.

There are four additional practice notes in the Skill, all of which have corresponding references in Stripe’s documentation: always verify webhook signatures; forward events locally using the Stripe CLI; save the Stripe Customer ID in the user table to avoid duplicate customer creation; fetch prices via the API instead of hardcoding them.

Installation and Activation

The Skill follows the standard SKILL.md format and can be used in tools that support Agent Skills such as Cursor, Claude Code, and Codex CLI. The following methods are sourced from the repository README, skills.sh, and the Cursor Skills documentation, and you only need to choose one.

Method 1: Manual Copy (Universal for Cursor)

The awesome-cursor-skills README states: place SKILL.md in .cursor/skills/ (project-level or user-level), and the Agent will automatically discover it.

mkdir -p .cursor/skills/adding-stripe
curl -o .cursor/skills/adding-stripe/SKILL.md \
  https://raw.githubusercontent.com/spencerpauly/awesome-cursor-skills/main/resources/adding-stripe/SKILL.md

According to Cursor’s documentation, project-level skills will also scan .agents/skills/; user-level skills correspond to ~/.cursor/skills/ and ~/.agents/skills/. To be compatible with other tools, Cursor will also load .claude/skills/, .codex/skills/, and their corresponding home directory paths. The directory structure should look like:

.cursor/skills/adding-stripe/SKILL.md

Method 2: Skills CLI (One-Click Installation for Multiple Agents)

The installation command provided by Vercel Skills CLI and skills.sh is as follows:

# List available Skills in the repository
npx skills add spencerpauly/awesome-cursor-skills --list

# Install only adding-stripe (for Cursor)
npx skills add spencerpauly/awesome-cursor-skills --skill adding-stripe -a cursor

# Install for Claude Code
npx skills add spencerpauly/awesome-cursor-skills --skill adding-stripe -a claude-code

# Install for Codex CLI
npx skills add spencerpauly/awesome-cursor-skills --skill adding-stripe -a codex

The equivalent syntax on the skills.sh page is:

npx skills add https://github.com/spencerpauly/awesome-cursor-skills --skill adding-stripe

The installation location is determined by the CLI’s detection: Cursor typically uses project-level .cursor/skills/ or .agents/skills/; Claude Code uses .claude/skills/; Codex uses ~/.codex/skills/ or project-level .codex/skills/.

No additional “activation” steps are usually required after installation. In Cursor, you can manually trigger the Skill by entering / in an Agent chat, searching for adding-stripe; the Agent may also automatically select it based on the description in the frontmatter when the conversation matches keywords like adding payments, subscriptions, or Stripe integration.

Typical Usage Examples

Trigger Methods

The Skill is designed to activate when a user requests to add payments, billing, subscriptions, or Stripe integration. You can directly say:
- “Connect Stripe subscriptions to this Next.js project”
- “Build a pricing page that redirects to Stripe Checkout when a button is clicked”
- “Write a Stripe webhook to synchronize subscription status to the database”
- “Let users manage their own subscriptions (Customer Portal)”

You can also explicitly enter /adding-stripe.

The Integration Flow the Agent Will Execute

The following steps are excerpted from the original Skill and cross-checked with Stripe’s official APIs to help verify the Agent’s output.

1. Install Dependencies

npm install stripe @stripe/stripe-js

2. Configure Environment Variables

Retrieve the secrets from Stripe Dashboard’s test mode, and the webhook signing secret printed when running stripe listen with the Stripe CLI:

STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

3. Create the Server-Side Stripe Client in lib/stripe.ts

See the example from the previous section. Never expose STRIPE_SECRET_KEY to the browser.

4. Create the Checkout API

The Session creation example from the Skill is as follows (switch mode for one-time payments or subscriptions):

const session = await stripe.checkout.sessions.create({
  mode: "subscription", // or "payment" for one-time
  payment_method_types: ["card"],
  line_items: [{ price: priceId, quantity: 1 }],
  success_url: `${origin}/success?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${origin}/pricing`,
  customer_email: userEmail,
});
return redirect(session.url!);

priceId should come from a Product/Price already created in the Dashboard, or from stripe.prices.list. The payment_method_types: ["card"] field is valid in the Checkout API; Stripe also allows omitting this field now, with available payment methods managed via the Dashboard instead. If your project requires additional local payment methods, do not assume the Agent will add them automatically.

5. Webhook: Verify the Signature Before Modifying Your Database

The Skill requires a POST /api/webhooks/stripe endpoint that uses constructEvent. Stripe’s documentation emphasizes that signature verification must use the unmodified raw request body. In Next.js App Router, you should first call request.text() instead of first parsing request.json() and re-serializing it, otherwise the signature verification will almost certainly fail. A typical Node.js implementation is:

const event = stripe.webhooks.constructEvent(
  rawBody,
  signature,
  process.env.STRIPE_WEBHOOK_SECRET!
);

Return a 4xx status code if signature verification fails, and do not proceed with further processing. After verification passes, update the local subscription status based on event.type.

For local debugging, use the Stripe CLI (the command given in the Skill matches the official CLI’s --forward-to flag):

stripe listen --forward-to localhost:3000/api/webhooks/stripe

The CLI will output a whsec_... value that you can add to STRIPE_WEBHOOK_SECRET. In production, register your HTTPS endpoint in the Dashboard and use the production signing secret instead.

6. Customer Portal (Optional)

Redirect the user after creating a portal Session on the server. A sample Stripe Node.js implementation is:

const session = await stripe.billingPortal.sessions.create({
  customer: customerId,
  return_url: "https://example.com/account",
});

This requires that you have already stored the Stripe Customer ID in your user table—exactly the detail emphasized in the Skill’s notes.

7. Pricing Page
Use plan cards that call the Checkout API. Prioritize fetching the price list via stripe.prices.list to avoid duplicating Price IDs in both frontend and backend code.

Applicable Scenarios and Notes

Who This Is For

  • Building SaaS/membership sites using Next.js (or similar Node.js web frameworks) that require one-time payments or subscriptions.
  • Using Agents like Cursor / Claude Code / Codex CLI to write code, and wanting a fixed checklist for “adding Stripe” to avoid missing steps like webhook signature verification and storing Customer IDs.
  • Accepting Stripe-hosted Checkout and the official Customer Portal, rather than building a full custom payment form from the start.

Usage Limitations and Notes

  1. This is a workflow guide, not an official Stripe Skill
    The repository page also links to Stripe plugins in the Cursor Marketplace (such as stripe-best-practices and upgrade-stripe). adding-stripe only covers the introductory path of Checkout + Webhooks + Portal, and does not include Connect, Payment Intents custom payment pages, tax, disputes, etc.

  2. Examples are bound to Next.js conventions
    Environment variable names, lib/stripe.ts, /api/webhooks/stripe, and localhost:3000 all follow common Next.js project structures. For Express, Remix, or non-Node.js backends, you need to specify the framework in your prompt and verify how to disable JSON middleware to preserve the raw request body for signature verification.

  3. API versions may become outdated
    The Skill hardcodes 2024-12-18.acacia. The type definitions in newer stripe npm packages usually only track the latest API version. If you encounter TypeScript errors or mismatched fields, refer to the current SDK and API versioning documentation instead of ignoring type checks forcefully.

  4. Webhooks must be verified, and must use the raw request body
    An unsecured /api/webhooks/stripe endpoint is a public POST route that allows attackers to fake checkout.session.completed events to activate subscriptions. Stripe explicitly requires HMAC signature verification; if your framework modifies the request body, constructEvent will fail.

  5. Secrets and test mode
    sk_ and whsec_ secrets should only be stored in environment variables, never committed to Git or included in client-side bundles. Test the flow in test mode first before switching to live keys and production webhook endpoints. You must first create Products and Prices in the Dashboard, otherwise line_items.price will throw an error directly.

  6. Portal and duplicate customers
    billingPortal.sessions.create requires an existing Customer. The Skill requires storing the Customer ID in the user table to avoid creating new customers for every Checkout session, which would cause the portal, invoices, and subscriptions to be tied to different user accounts.

  7. Agent output still requires manual review
    The Skill will not handle PCI scope assessment, tax, invoice compliance, or refund policies for you. The generated routes, permission activation logic, and idempotent processing (Stripe will retry webhooks) need to be verified against your business requirements.

Summary

adding-stripe turns the most common commercial path for Stripe in web applications—installing SDKs, configuring secrets, Checkout Session, webhook signature verification, optional Customer Portal, and pricing pages—into a 7-step checklist that Agents can follow. It does not expand Stripe’s native capabilities, but reduces the chance of common integration errors like missing signature verification, failing to store Customer IDs, or exposing secrets in frontend code.

Official Skill address: https://github.com/spencerpauly/awesome-cursor-skills/tree/main/resources/adding-stripe

Related documentation:
- Stripe Checkout Session: https://docs.stripe.com/api/checkout/sessions/create
- Webhooks: https://docs.stripe.com/webhooks
- Customer Portal: https://docs.stripe.com/customer-management/integrate-customer-portal
- Cursor Skills: https://cursor.com/docs/skills