Stripe | Financial Infrastructure to Grow Your Revenue

Stripe | Financial Infrastructure to Grow Your Revenue

4466 articles

How extensions work


Private preview

How extensions work Private preview

Learn how you can customize Stripe with extensions.

Extensions let you run custom logic at designated places in Stripe called extension points. When Stripe has to run the logic at these extension points, it checks if an extension is plugged into them and if found, runs the custom logic in the extension.

For example, Stripe defines an extension point for prorations. When Stripe reaches the proration calculation step, it runs your extension’s logic instead of the default proration logic. Your extension determines how to prorate, returns the amount, and Stripe continues the billing flow with that result.

Stripe also defines a custom action extension point for Workflows. When a workflow triggers, Stripe calls your extension to send an email, update a CRM, or perform any other operation you define.

How the model works

Stripe defines extension points, designated places in Stripe products where your code can run. Each extension point specifies:

  • Input : The data Stripe sends to your extension when the extension point is reached, including input from the extension user
  • Output : The data your extension must return to Stripe
  • Allowed implementation types : Which implementation types (scripts, remote functions, or both) you can use at that extension point

Start by finding the extension point for your use case.

You build your custom logic as an extension that plugs into an extension point. We package extensions as part of Stripe Apps, which handles installation, permissions, and distribution. You can have multiple extensions packaged within the same app, of any implementation type: scripts, remote functions, or UI extensions. Apps can also contain custom objects.

Implementation types

Each extension point supports one or more implementation types. The implementation type determines where your code runs and how it interacts with external services.

Choose an implementation type

If an extension point supports both scripts and remote functions, use this table to decide:

ConsiderationScriptRemote function
Where it runsStripe managed runtimeYour infrastructure
LanguageTypeScriptAny language (HTTP endpoint)
External API callsExtension-point-dependent. Allowed for custom actions (through endpointFetch()). Not allowed for billing extension points.Yes, you make calls directly from your servers
Authorization for external servicesStripe injects secrets through the endpoint configuration and the Secret Store (where external API calls are allowed)You manage authentication yourself
Authorization from Stripe to your codeN/A, your code runs on StripeStripe signs each request. You verify the webhook signature.
Best forLogic that doesn’t need your own infrastructureLogic that needs your own systems, transforms, or non-TypeScript languages
LimitationsNo third-party dependencies, no raw fetch(), TypeScript onlyYou manage hosting, availability, and deployment

Scripts

Scripts are TypeScript methods that run on the Stripe fully managed runtime. You don’t need to host infrastructure because Stripe runs your code and you deploy by uploading your app through the Stripe CLI.

Scripts run your business logic when Stripe reaches an extension point. Use scripts when you need to:

  • Apply complex business rules using code, such as calculating a discount based on customer purchase history and sales events.
  • Validate or transform data before Stripe processes it, such as checking if a customer meets eligibility criteria.
  • Integrate external data into Stripe operations without building and maintaining webhooks.
  • Prototype quickly without deploying and managing your own services.

What scripts can do depends on the extension point:

  • At billing extension points (customer balance, item handling, prorations): Scripts receive data from Stripe, run your logic, and return a result. External API calls aren’t permitted. These extension points run in the billing pipeline, where Stripe restricts side effects to maintain reliability.
  • At the custom action extension point (for Workflows): Scripts can make external HTTP calls using endpointFetch() . You declare endpoints in your app manifest, and Stripe handles secret storage and authentication injection through the Secret Store . This is designed for actions that reach external services without requiring you to manage infrastructure.

Use cases

Use caseBilling behaviorScriptDescription
Set a minimum charge threshold.Customer balanceMinimum amount before collectionUse this script to avoid collecting on small invoices by deferring them to the customer balance until the total owed reaches a threshold you define. Use it when you want to accumulate charges across billing cycles before collecting, or avoid charging customers for small amounts.
Set a maximum of credit to apply to a single invoice.Customer balanceMaximum credit per invoiceUse this script when you want to spread credits across multiple billing cycles instead of applying them all at once, or when business rules require limiting credit usage per invoice.
Put metered usage items and licensed items on separate invoices.Invoice item creation and routingSeparate invoice for metered itemsUse this script when your finance team needs to reconcile usage charges separately from recurring seat or license fees, or when your customers expect different invoices for them.
Calculate prorations by hours, days, weeks, or months.ProrationProrate by custom intervalUse this script whenever your business needs proration calculated in units larger than a second, whether to match regional billing conventions, align with contractual terms, or reduce customer confusion caused by fractional amounts.
Refund or charge the full amount for some items in a subscription.ProrationCredit and debit full product priceUse this script when certain products on a subscription aren’t prorated. For example, a flat support fee or a platform access charge that’s always billed in full regardless of when the subscription changes.

Limitations

Most TypeScript features work on Stripe’s runtime, but the following patterns aren’t available. The build and upload steps catch these automatically:

  • Code evaluation such as eval() or new Function()
  • Timer functions such as setTimeout() , setInterval() , and setImmediate()
  • Global scope access via global or globalThis
  • Process APIs such as process. exit() or process. env
  • console. log() . Use Workbench to view script run logs.
  • Embedded API keys or secrets. Use the Stripe secret store to manage sensitive values.
  • Network access APIs such as fetch() . Use endpointFetch() to invoke endpoints from a script .

Stripe doesn’t currently support third-party libraries as dependencies.

Remote functions

Remote functions are HTTP endpoints that you host on your own infrastructure. Stripe calls your endpoint when the extension point is reached, signing each request with a webhook signature so you can verify it came from Stripe.

You manage authentication for any external services your code calls, Stripe doesn’t inject secrets for remote functions. You verify the incoming Stripe signature, and you handle outgoing authorization yourself.

Use remote functions when you need to:

  • Run logic on your own servers or in your own environment
  • Integrate with your own systems such as an ERP or CRM
  • Use a language other than TypeScript

Limitations

Remote functions currently have the following limitations:

  • You manage hosting, availability, and deployment.
  • Your endpoints must respond within the timeout defined by the extension point (for example, 20 seconds for custom actions).

UI extensions

React components that display inside the Stripe Dashboard. Use a UI extension to present custom UI to Dashboard users. See UI extensions.

Permissions

When you build an extension, you must declare the permissions your extension needs. An extension can only access the data it has been granted permission to read or write. Users of extensions grant these permissions when installing the app that contains the extensions. See a complete list of all permissions.

Connected accounts

Your configured extensions don’t apply to your connected accounts. Connected accounts must configure the extension independently in their installed app.

Lifecycle

An extension can follow this lifecycle. Versioning, publishing, deprecation, and archival are optional:

  1. Build : You build an extension within a Stripe app.
  2. Upload : You upload the app using the Stripe CLI. Stripe processes it and makes it available to install.
  3. (Optional) Version : You upload new versions as you iterate.
  4. (Optional) Publish : You share the app through an external testing channel or the Stripe App Marketplace . It becomes available to install in their accounts.
  5. Install : You, or those the app is shared with, install it, accepting associated permissions.
  6. Activate : The app user activates an extension at its extension point.
  7. Invoke : Stripe calls the activated extension whenever it reaches the extension point.
  8. (Optional) Deprecate : The app user is prevented from activating a version of an extension, but extensions already activated on that version continue to run.
  9. (Optional) Archive : Activated extensions are moved to a compatible version, or prevented from running if a version is not defined.
  10. Deactivate : The app user deactivates the extension. It remains on the account but Stripe no longer calls it when it reaches the extension point.
  11. Uninstall : The app user removes the app and its extensions from the account.

Get started building

If you’re here for billing customizations, start with the step-by-step guide: Create a billing script extension. It covers prerequisites, app creation, CLI commands, and uploading.

The guide you follow otherwise depends on which extension point you’re building for:

For a complete list of available extension points and their supported implementation types, see extension points.

Last verified 2026-09-24

Is this helpful?