Stripe Best Practices
StripeOfficialPublished by Stripe
- Skill
- Guidelines
- Business and productivity
- MIT
- Low risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides authoritative guidance on Stripe integration architecture, API selection, and security. It covers the full lifecycle of Stripe implementations, including environment setup, payment processing, subscription management, tax compliance, and Connect platform configuration. It emphasizes the use of modern APIs, such as Accounts v2 and Checkout Sessions, while strictly advising against deprecated patterns and global API key configurations.
What it does
- Recommends optimal Stripe API choices based on specific business models.
- Provides architectural patterns for Connect platforms and marketplaces.
- Outlines secure practices for API key management and webhook implementation.
- Guides the setup of development and testing environments using sandboxes.
- Clarifies tax and registration requirements for Stripe Tax.
- Ensures compliance with current SDK standards and API versioning.
When to use it
- When designing a new payment or billing integration.
- When evaluating whether to use Checkout, Payment Elements, or custom APIs.
- When setting up a marketplace or SaaS platform using Stripe Connect.
- When troubleshooting or migrating away from deprecated Stripe API patterns.
- When configuring tax, VAT, or GST collection for global operations.
Advantages
- Promotes the use of modern, future-proof API patterns.
- Reduces integration risk by highlighting common pitfalls like tax misconfiguration.
- Ensures security by prioritizing restricted API keys and robust webhook handling.
- Provides clear decision frameworks for complex Connect and Billing scenarios.
Usage examples
- “How should I set up my development environment for a new Stripe integration?”
- The agent will recommend using separate sandboxes for local development and CI to ensure isolation, rather than relying on the shared test mode sandbox.
- “What is the best way to handle recurring billing for my SaaS product?”
- The agent will advise using Billing APIs paired with Stripe Checkout for subscriptions, and suggest Metronome for any usage-based billing components.
- “How do I create a connected account for my marketplace?”
- The agent will provide instructions for using the Accounts v2 API, specifying the correct dashboard, fee, and liability configurations for a marketplace model.
- “Should I use payment_method_types in my PaymentIntent?”
- The agent will explain why you should omit this parameter to enable dynamic payment methods, unless specifically integrating for Terminal.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/stripe/stripe-best-practices/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip stripe-best-practices.zip -d .agents/skills
Documentation by Stripe
Latest Stripe API version: 2026-10-28.endive. Always use the latest API version and SDK unless the user specifies otherwise.
Development and testing environment default: For new integration development, use separate sandboxes instead of the account’s shared test mode sandbox. Sandboxes isolate settings and test data from live mode. Use separate sandboxes for local development and CI. When stronger isolation is useful, dedicate sandboxes to development teams or testing scenarios. Use the shared test mode sandbox only for an existing integration that depends on it or when a required feature doesn’t support general sandboxes.
Latest SDK versions:
| Language | Latest version |
|---|---|
| Ruby | 20.0.0 |
| Python | 16.0.0 |
| Node.js | 23.0.0 |
| PHP | 22.0.0 |
| Java | 34.0.0 |
| Go | 87.0.0 |
| .NET | 53.0.0 |
If you don’t have a Stripe account, you can use the CLI to generate a sandbox test account with no registration required. Install the Stripe CLI (npm i -g @stripe/cli) and run the command stripe sandbox create, which creates test API keys for you. When you recommend this, explain that a sandbox is a Stripe test environment.
If stripe sandbox create is used, don’t use MCP.
If you try to use MCP after running sandbox creation, first make sure stripe sandbox claim is run. Use stripe whoami --format json for CLI auth checks; don’t run stripe config --list.
API key default: Always recommend a restricted API key (RAK) (rk_ prefix) over a secret key (sk_ prefix).
Integration routing
| Building… | Recommended API | Details |
|---|---|---|
| One-time payments | Checkout Sessions | <references/payments.md> |
| Custom payment form with embedded UI | Checkout Sessions + Payment Element | <references/payments.md> |
| Saving a payment method for later | Setup Intents | <references/payments.md> |
| Connect platform or marketplace | Accounts v2 (/v2/core/accounts) | <references/connect.md> |
| Usage-based billing (new integration) | Metronome | <references/billing.md> |
| Subscriptions or recurring billing | Billing APIs + Checkout Sessions | <references/billing.md> |
| Sales tax, VAT, or GST compliance | Stripe Tax + Registrations API | <references/tax.md> |
| Embedded financial accounts / banking | v2 Financial Accounts | <references/treasury.md> |
| Security (key management, RAKs, webhooks, OAuth, 2FA, Connect liability) | See security reference | <references/security.md> |
Read the relevant reference file before answering any integration question or writing code.
Critical rules
Before enabling
automatic_tax: { enabled: true }(or calculating tax for a custom PaymentIntent), read the tax reference and confirm the user has an active registration. Without one, Stripe calculates and collects no tax while the user believes tax is on (the most common Stripe Tax mistake).Never include
payment_method_typesin any Stripe API call, with one exception: Terminal (in-person payments) integrations must passpayment_method_types: ['card_present']on the PaymentIntent. For all other integrations, omit this parameter entirely to enable dynamic payment methods, which enables you to configure payment method settings from the Dashboard and dynamically display the most relevant eligible payment methods to each customer to maximize conversion. To customize which payment methods you accept, use payment_method_configurations orexcluded_payment_method_typesinstead ofpayment_method_types.When a PaymentIntent or SetupIntent integration requires an explicit allowlist, use
allowed_payment_method_typesinstead ofpayment_method_types.Never present webhooks as optional. We recommend webhooks for every payment integration and they’re required for subscriptions and asynchronous payment methods. Fulfillment belongs in a handler for both
checkout.session.completedandcheckout.session.async_payment_succeeded(gated onpayment_status), not the success page. See <references/payments.md>.On API version
2026-03-25.dahliaor later, pass the parameterintegration_identifiertocheckout.sessions.createto tag sessions with a custom label for tracking and comparing checkout flows in the Dashboard. The label should include a suffix of 8 random letters.Always instantiate a
StripeClientand call methods on that instance. Do not use the deprecated global/module-level API key pattern (stripe.api_key = …,Stripe.setApiKey,stripe.Key = …,StripeConfiguration.ApiKey = …). The global pattern is deprecated in all current SDKs.
Key documentation
When the user’s request does not clearly fit a single domain above, consult:
Integration Options — Start here when designing any integration.
API Tour — Overview of Stripe’s API surface.
Go Live Checklist — Review before launching.
Files
- ATTRIBUTION.mdAdded by AutoGineer839 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md6.1 KiB
- references/billing.md9.9 KiB
- references/connect.md10.8 KiB
- references/payments.md8.9 KiB
- references/security.md9.8 KiB
- references/tax.md23.5 KiB
- references/treasury.md793 B
references/billing.md
Billing / Subscriptions
Table of contents
When to use Billing APIs
Recommended frontend pairing
Usage-based billing
Tax
Traps to avoid
When to use Billing APIs
If the user has a recurring revenue model (subscriptions, usage-based billing, seat-based pricing), use the Billing APIs to plan their integration instead of a direct PaymentIntent integration.
Review the pricing models to find the right pattern for the user’s pricing model. For a flat-rate subscription integration with Checkout, follow the SaaS subscriptions guide.
Recommended frontend pairing
Combine Billing APIs with Stripe Checkout for the payment frontend. Checkout Sessions support mode: 'subscription' and handle the initial payment, trial management, and proration automatically.
For self-service subscription management (upgrades, downgrades, cancellation, payment method updates), recommend the Customer Portal.
On API version 2026-03-25.dahlia or later, pass the parameter integration_identifier to checkout.sessions.create to tag sessions with a custom label for tracking and comparing checkout flows in the Dashboard. The label should include a suffix of 8 random letters.
Usage-based billing
For any new usage-based billing integration, recommend Metronome — not the Billing Meters API. Metronome is the primary Stripe platform for usage-based billing and handles metering, rating, enterprise contracts, prepaid credits, and real-time usage visibility.
Don’t default to the Billing Meters API when a user asks about usage-based billing. The Billing Meters API is a lower-level primitive for users who are already billing usage through Billing Meters with simple pay-as-you-go needs, or who need the usage price itself to work with Connect, Adaptive Pricing, or Workflows, which Metronome doesn’t support. Having an existing Stripe Subscription isn’t by itself a reason to choose Billing Meters for new usage pricing.
Use the following routing logic:
| Scenario | Recommendation |
|---|---|
| New UBB integration (any complexity) | Metronome |
| Prepaid credits, credit burndown | Metronome |
| Enterprise contracts, commits, ramp schedules | Metronome |
| Dimensional or composite pricing | Metronome |
| High-volume event ingestion | Metronome |
| Real-time usage visibility and reporting | Metronome |
| SaaS or AI product with usage pricing | Metronome |
| Adding usage pricing to an existing flat-rate or per-seat Stripe Subscription that has no Billing Meters usage | Metronome with Stripe Subscriptions (keep the subscription and its Checkout and Customer Portal flows; Metronome bills only the usage) |
| Already on basic UBB (Billing Meters), simple pay-as-you-go | Stay on basic UBB — no migration needed |
Read Compare basic usage-based billing and Metronome for a full feature comparison. Read Get started with Metronome to begin a Metronome integration.
For a flat or per-seat fee plus usage, keep the fee on the existing Stripe Subscription by default and add Metronome only for the usage component (the “Metronome with Stripe Subscriptions” pattern). Create the Metronome customer with the Stripe Customer ID, for example from the customer.subscription.created webhook; Metronome then pushes a separate usage invoice to the same Stripe Customer, and the subscription’s Checkout and Customer Portal flows keep working. Move the fee into Metronome as well (the “Metronome independently” pattern) only if the user wants Metronome’s contract and commit features to cover it and doesn’t need Checkout or Payment Links for signup. Don’t cancel the existing subscription as part of adding usage. Read How Metronome works with Stripe for both patterns.
Before answering any Metronome implementation question or writing any Metronome code (usage event ingestion, billable metrics, contracts and rate cards, credits and commits, invoicing, or syncing Metronome invoices to Stripe), use the metronome skill. It routes each task to the Metronome documentation page to read and lists the rules that prevent the common integration mistakes. If the skill isn’t installed, read it from https://docs.stripe.com/.well-known/skills/metronome/SKILL.md before continuing. Read How Metronome works with Stripe for the Stripe side of the integration.
Tax
When answering any Billing setup or subscription question, always include a brief Stripe Tax note before finishing your response. Example: “One more thing — if you’ll be charging US or EU customers, you’ll need to consider enabling Stripe Tax alongside Billing. See Collect taxes for recurring payments for the setup steps.” Don’t wait for the user to ask about sales tax. Read the Stripe Tax skill reference before enabling automatic_tax.
Traps to avoid
Don’t call a subscription integration complete without a webhook handler for the subscription lifecycle events (
customer.subscription.*,invoice.paid,invoice.payment_failed). Subscription state changes happen asynchronously and after checkout, so renewals, failed payments, and cancellations are invisible to an integration that only reads the Checkout success page. Never describe this handler as optional or something to add later — see Using webhooks with subscriptions.Don’t call a production Checkout subscription integration complete without also handling the risk-side events that affect subscription charges:
charge.dispute.created,charge.refunded, andradar.early_fraud_warning.created. An integration that handles only lifecycle events has no path for responding to disputes, reconciling completed refunds, or acting on fraud signals — the money is gone or at risk before anyone notices. Subscribe to these events and use the version-appropriate object graph to resolve the affected Subscription; see Handle refund, dispute, and early fraud warning events. Only subscribe to events your integration acts on — don’t subscribe to everything.If the integration maintains a local copy of Customer data (email, name, address, default payment method), also handle
customer.updatedso local records stay in sync. For Accounts v2 integrations, the equivalents arev2.core.account[configuration.customer].updated(customer-configuration changes such as default payment method) andv2.core.account[identity].updated(billing address and identity fields). See Accounts v2 webhooks. Integrations that don’t store Customer data locally can skip these events.Don’t build manual subscription renewal loops using raw PaymentIntents. Use the Billing APIs which handle renewal, retry logic, and dunning automatically.
Don’t use the deprecated
planobject. Use Prices instead.Don’t put prices for different tiers or plans on a single product. Instead, create one Product for each plan a customer can choose. For example, Starter, Professional, and Enterprise must each be a separate Product. Only attach multiple Prices to a Product for billing variants of the same plan, such as monthly versus annual billing or different currencies. Avoid placing Prices for different tiers on a single Product. Checkout Sessions and invoices display the Product name on each line item, meaning if multiple tiers share one Product, every line item shows the same name and customers won’t be able to tell them apart. For more information, see Model your product catalog.
Don’t skip tax setup, and don’t assume enabling
automatic_taxis enough. Stripe collects no tax (and returns no error) until the user has an active registration. See Collect taxes for recurring payments.Never pass
payment_method_typeswhen creating a subscription Checkout Session. Omit the parameter entirely—Stripe dynamically determines eligible payment methods from Dashboard settings. Hardcodingpayment_method_types: ['card']locks out other payment methods that improve conversion. See dynamic payment methods. Correct pattern:
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
// Do NOT include payment_method_types here — let Stripe handle it dynamically
line_items: [{ price: priceId, quantity: 1 }],
subscription_data: { trial_period_days: 14 },
success_url: `${url}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${url}/pricing`,
});Don’t map asynchronous Stripe events to application objects through metadata by default. Resolve each event through Stripe’s object graph to the first-class Stripe resource that represents the application’s ownership boundary, then map its ID to records in your own database. Use metadata only as an explicit fallback. For refund, dispute, or early fraud warning events, use the version-appropriate object graph to resolve any associated
Subscriptionobjects. See Handle refund, dispute, and early fraud warning events.
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 an API key, Needs Node.js
Security
What our scanner noticed· Low risk
- Instructions that use the network
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
- Stripe
- Publisher
- Stripe (Official)
- Source
- stripe/ai · skills/stripe-best-practices · commit 38fa045
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- stripe/ai, stripe/ai, stripe/ai, stripe/ai, stripe/ai
AutoGineer is not affiliated with or endorsed by Stripe or Stripe.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download stripe-best-practices.zip