# How extensions work

Learn how you can customize Stripe with extensions.

Extensions let you run custom logic at designated places in Stripe called [extension points](https://docs.stripe.com/extensions/extension-points.md). 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](https://docs.stripe.com/extensions/scripts/build-prorations-extension.md). You use an extension built for this extension point. When Stripe reaches the proration calculation step, it runs your extension’s logic instead of the default proration logic. The extension’s logic decides how to prorate and returns the proration amount. Stripe uses the result and continues the billing flow. Similarly, in [Workflows](https://docs.stripe.com/extensions/custom-actions/how-custom-actions-work.md) Stripe defines a custom action extension point. An extension for it calls your code 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
 (See full diagram at https://docs.stripe.com/extensions/how-extensions-work)
Start by finding the [extension point](https://docs.stripe.com/extensions/extension-points.md) for your use case.

You build your custom logic as an extension that plugs into an extension point. Extensions are packaged as part of [Stripe Apps](https://docs.stripe.com/stripe-apps.md), which handle installation, permissions, and distribution. You can have multiple extensions packaged within the same app, of any implementation type: [scripts](https://docs.stripe.com/extensions/how-extensions-work.md#scripts), [remote functions](https://docs.stripe.com/extensions/how-extensions-work.md#remote-functions), or [UI extensions](https://docs.stripe.com/extensions/how-extensions-work.md#ui-extensions). Apps can also contain [custom objects](https://docs.stripe.com/custom-objects.md).

## 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.

### Scripts

Scripts are TypeScript methods that run on Stripe’s 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](https://docs.stripe.com/stripe-apps/store-secrets.md). This is designed for actions that reach external services without requiring you to manage infrastructure.

**Limitations:** No third-party dependencies. External API calls only for Workflows custom actions using `endpointFetch()`. Supports TypeScript only. See [script runtime behavior](https://docs.stripe.com/extensions/scripts/build-prorations-extension.md#script-runtime-behavior) for the full list of constraints.

### 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](https://docs.stripe.com/webhooks.md#verify-official-libraries) 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 auth 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:** 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 appear inside the Stripe Dashboard. Use a UI extension to surface custom UI to Dashboard users. See [UI extensions](https://docs.stripe.com/stripe-apps/how-ui-extensions-work.md).

### Choosing an implementation type

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

| Consideration                 | Script                                                                                                                                                                 | Remote function                                                                                                               |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Where it runs                 | Stripe’s managed runtime                                                                                                                                               | Your infrastructure                                                                                                           |
| Language                      | TypeScript                                                                                                                                                             | Any language (HTTP endpoint)                                                                                                  |
| External API calls            | Extension-point-dependent. Allowed for custom actions (through `endpointFetch()`). Not allowed for billing extension points.                                           | Yes, you make calls directly from your servers                                                                                |
| Auth for external services    | Stripe injects secrets through the endpoint config and the [Secret Store](https://docs.stripe.com/stripe-apps/store-secrets.md) (where external API calls are allowed) | You manage authentication yourself                                                                                            |
| Auth from Stripe to your code | N/A, your code runs on Stripe                                                                                                                                          | Stripe signs each request. You [verify the webhook signature](https://docs.stripe.com/webhooks.md#verify-official-libraries). |
| Best for                      | Logic that doesn’t need your own infrastructure                                                                                                                        | Logic that needs your own systems, transforms, or non-TypeScript languages                                                    |
| Limitations                   | No third-party dependencies, no raw `fetch()`, TypeScript only                                                                                                         | You manage hosting, availability, and deployment                                                                              |

## 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](https://docs.stripe.com/stripe-apps/reference/permissions.md).

## Lifecycle

Creating an extension follows this lifecycle:

1. **Build**: You build an extension within a Stripe App.
1. **Upload**: You upload the app using the Stripe CLI. Stripe processes it and makes it available to install.
1. **Version** (optional): You upload new versions as you iterate.
1. **Publish** (optional): You share the app through an [external testing channel](https://docs.stripe.com/stripe-apps/test-app.md) or the [Stripe App Marketplace](https://docs.stripe.com/stripe-apps/publish-app.md). It becomes available to install in their accounts.
1. **Install**: You, or those the app is shared with, install it, accepting associated permissions.
1. **Activate**: The app user activates an extension at its extension point.
1. **Invoke**: Stripe calls the activated extension whenever it reaches the extension point.
1. **Deactivate**: The app user deactivates the extension. It remains on the account but Stripe no longer calls it when it reaches the extension point.
1. **Uninstall**: The app user removes the app and its extensions from the account.

## Get started building

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

- [Create a billing script extension](https://docs.stripe.com/extensions/scripts/build-prorations-extension.md) to customize customer balance, item handling, or prorations behavior.
- [Create a custom workflow action with a script](https://docs.stripe.com/extensions/custom-actions/build-with-script.md) or [remote functions](https://docs.stripe.com/extensions/custom-actions/build-with-remote-function.md). Learn more about [How custom actions work](https://docs.stripe.com/extensions/custom-actions/how-custom-actions-work.md).

For a complete list of available extension points and their supported implementation types, see [extension points](https://docs.stripe.com/extensions/extension-points.md).
