# Breaking Changes
Source: https://www.activepieces.com/docs/about/breaking-changes

This list shows all versions that include breaking changes and how to upgrade.

## 0.46.0

### What has changed?

* The UI for "Array of Properties" inputs in the pieces has been updated, particularly affecting the "Dynamic Value" toggle functionality.

### When is action necessary?

* No action is required for this change.
* Your published flows will continue to work without interruption.
* When editing existing flows that use the "Dynamic Value" toggle on "Array of Properties" inputs (such as the "files" parameter in the "Extract Structured Data" action of the "Utility AI" piece), the end user will need to remap the values again.
* For details on the new UI implementation, refer to this [announcement](https://community.activepieces.com/t/inline-items/8964).

## 0.38.6

### What has changed?

* Workers no longer rely on the `AP_FLOW_WORKER_CONCURRENCY` and `AP_SCHEDULED_WORKER_CONCURRENCY` environment variables. These values are now retrieved from the app server.

### When is action necessary?

* If `AP_CONTAINER_TYPE` is set to `WORKER` on the worker machine, and `AP_SCHEDULED_WORKER_CONCURRENCY` or `AP_FLOW_WORKER_CONCURRENCY` are set to zero on the app server, workers will stop processing the queues. To fix this, check the [Separate Worker from App](https://www.activepieces.com/docs/install/configuration/separate-workers) documentation and set the `AP_CONTAINER_TYPE` to fetch the necessary values from the app server. If no container type is set on the worker machine, this is not a breaking change.

## 0.35.1

### What has changed?

* The 'name' attribute has been renamed to 'externalId' in the `AppConnection` entity.
* The 'displayName' attribute has been added to the `AppConnection` entity.

### When is action necessary?

* If you are using the connections API, you should update the `name` attribute to `externalId` and add the `displayName` attribute.

## 0.35.0

### What has changed?

* All branches are now converted to routers, and downgrade is not supported.

## 0.33.0

### What has changed?

* Files from actions or triggers are now stored in the database / S3 to support retries from certain steps, and the size of files from actions is now subject to the limit of `AP_MAX_FILE_SIZE_MB`.
* Files in triggers were previously passed as base64 encoded strings; now they are passed as file paths in the database / S3. Paused flows that have triggers from version 0.29.0 or earlier will no longer work.

### When is action necessary?

* If you are dealing with large files in the actions, consider increasing the `AP_MAX_FILE_SIZE_MB` to a higher value, and make sure the storage system (database/S3) has enough capacity for the files.

## 0.30.0

### What has changed?

* `AP_SANDBOX_RUN_TIME_SECONDS` is now deprecated and replaced with `AP_FLOW_TIMEOUT_SECONDS`
* `AP_CODE_SANDBOX_TYPE` is now deprecated and replaced with new mode in `AP_EXECUTION_MODE`

### When is action necessary?

* If you are using `AP_CODE_SANDBOX_TYPE` to `V8_ISOLATE`, you should switch to `AP_EXECUTION_MODE` to `SANDBOX_CODE_ONLY`
* If you are using `AP_SANDBOX_RUN_TIME_SECONDS` to set the sandbox run time limit, you should switch to `AP_FLOW_TIMEOUT_SECONDS`

## 0.28.0

### What has changed?

* **Project Members:**
  * The `EXTERNAL_CUSTOMER` role has been deprecated and replaced with the `OPERATOR` role. Please check the permissions page for more details.
  * All pending invitations will be removed.
  * The User Invitation entity has been introduced to send invitations. You can still use the Project Member API to add roles for the user, but it requires the user to exist. If you want to send an email, use the User Invitation, and later a record in the project member will be created after the user accepts and registers an account.
* **Authentication:**
  * The `SIGN_UP_ENABLED` environment variable, which allowed multiple users to sign up for different platforms/projects, has been removed. It has been replaced with inviting users to the same platform/project. All old users should continue to work normally.

### When is action necessary?

* **Project Members:**

If you use the embedding SDK or the create project member API with the `EXTERNAL_CUSTOMER` role, you should start using the `OPERATOR` role instead.

* **Authentication:**

Multiple platforms/projects are no longer supported in the community edition. Technically, everything is still there, but you have to hack using the API as the authentication system has now changed. If you have already created the users/platforms, they should continue to work, and no action is required.


# Changelog
Source: https://www.activepieces.com/docs/about/changelog

A log of all notable changes to Activepieces



# Editions
Source: https://www.activepieces.com/docs/about/editions



Activepieces operates on an open-core model, providing a core software platform as open source licensed under the permissive **MIT** license while offering additional features as proprietary add-ons in the cloud.

### Community / Open Source Edition

The Community edition is free and open source. It has all the pieces and features to build and run flows without any limitations.

### Commercial Editions

Learn more at: [https://www.activepieces.com/pricing](https://www.activepieces.com/pricing)

## Feature Comparison

| Feature                  | Community | Enterprise | Embed    |
| ------------------------ | --------- | ---------- | -------- |
| Flow History             | ✅         | ✅          | ✅        |
| All Pieces               | ✅         | ✅          | ✅        |
| Flow Runs                | ✅         | ✅          | ✅        |
| Unlimited Flows          | ✅         | ✅          | ✅        |
| Unlimited Connections    | ✅         | ✅          | ✅        |
| Unlimited Flow steps     | ✅         | ✅          | ✅        |
| Custom Pieces            | ✅         | ✅          | ✅        |
| On Premise               | ✅         | ✅          | ✅        |
| Cloud                    | ❌         | ✅          | ✅        |
| Project Team Members     | ❌         | ✅          | ✅        |
| Manage Multiple Projects | ❌         | ✅          | ✅        |
| Limits Per Project       | ❌         | ✅          | ✅        |
| Pieces Management        | ❌         | ✅          | ✅        |
| Templates Management     | ❌         | ✅          | ✅        |
| Custom Domain            | ❌         | ✅          | ✅        |
| All Languages            | ✅         | ✅          | ✅        |
| JWT Single Sign On       | ❌         | ❌          | ✅        |
| Embed SDK                | ❌         | ❌          | ✅        |
| Audit Logs               | ❌         | ✅          | ❌        |
| Git Sync                 | ❌         | ✅          | ❌        |
| Private Pieces           | ❌         | <b>5</b>   | <b>2</b> |
| Custom Email Branding    | ❌         | ✅          | ✅        |
| Custom Branding          | ❌         | ✅          | ✅        |


# i18n Translations
Source: https://www.activepieces.com/docs/about/i18n



This guide helps you understand how to change or add new translations.

Activepieces uses Crowdin because it helps translators who don't know how to code. It also makes the approval process easier. Activepieces automatically sync new text from the code and translations back into the code.

## Contribute to existing translations

1. Create Crowdin account
2. Join the project [https://crowdin.com/project/activepieces](https://crowdin.com/project/activepieces)

![Join Project](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/crowdin.png)

3. Click on the language you want to translate

4. Click on "Translate All"

![Translate All](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/crowdin-translate-all.png)

5. Select Strings you want to translate and click on "Save" button

## Adding a new language

* Please contact us ([support@activepieces.com](mailto:support@activepieces.com)) if you want to add a new language. We will add it to the project and you can start translating.


# License
Source: https://www.activepieces.com/docs/about/license



Activepieces' **core** is released as open source under the [MIT license](https://github.com/activepieces/activepieces/blob/main/LICENSE) and enterprise / cloud editions features are released under [Commercial License](https://github.com/activepieces/activepieces/blob/main/packages/ee/LICENSE)

The MIT license is a permissive license that grants users the freedom to use, modify, or distribute the software without any significant restrictions. The only requirement is that you include the license notice along with the software when distributing it.

Using the enterprise features (under the packages/ee and packages/server/api/src/app/ee folder) with a self-hosted instance requires an Activepieces license. If you are looking for these features, contact us at [sales@activepieces.com](mailto:sales@activepieces.com).

**Benefits of Dual Licensing Repo**

* **Transparency** - Everyone can see what we are doing and contribute to the project.
* **Clarity** - Everyone can see what the difference is between the open source and commercial versions of our software.
* **Audit** - Everyone can audit our code and see what we are doing.
* **Faster Development** - We can develop faster and more efficiently.

<Tip>
  If you are still confused or have feedback, please open an issue on GitHub or send a message in the #contribution channel on Discord.
</Tip>


# Telemetry
Source: https://www.activepieces.com/docs/about/telemetry



# Why Does Activepieces need data?

As a self-hosted product, gathering usage metrics and insights can be difficult for us. However, these analytics are essential in helping us understand key behaviors and delivering a higher quality experience that meets your needs.

To ensure we can continue to improve our product, we have decided to track certain basic behaviors and metrics that are vital for understanding the usage of Activepieces.

We have implemented a minimal tracking plan and provide a detailed list of the metrics collected in a separate section.

# What Does Activepieces Collect?

We value transparency in data collection and assure you that we do not collect any personal information. The following events are currently being collected:

[Exact Code](https://github.com/activepieces/activepieces/blob/main/packages/shared/src/lib/common/telemetry.ts)

1. `flow.published`: Event fired when a flow is published
2. `signed.up`: Event fired when a user signs up
3. `flow.test`: Event fired when a flow is tested
4. `flow.created`: Event fired when a flow is created
5. `start.building`: Event fired when a user starts building
6. `demo.imported`: Event fired when a demo is imported
7. `flow.imported`: Event fired when a flow template is imported

# Opting out?

To opt out, set the environment variable `AP_TELEMETRY_ENABLED=false`


# Appearance
Source: https://www.activepieces.com/docs/admin-console/appearance



<Snippet file="enterprise-feature.mdx" />

Customize the brand by going to the **Appearance** section under **Settings**. Here, you can customize:

* Logo / FavIcon
* Primary color
* Default Language

<video controls autoplay muted loop playsinline className="w-full aspect-video" src="https://cdn.activepieces.com/videos/showcase/appearance.mp4" />


# Custom Domains
Source: https://www.activepieces.com/docs/admin-console/custom-domain



<Snippet file="enterprise-feature.mdx" />

You can set up a unique domain for your platform, like app.example.com.

This is also used to determine the theme and branding on the authentication pages when a user is not logged in.

![Manage Projects](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/custom-domain.png)


# Customize Emails
Source: https://www.activepieces.com/docs/admin-console/customize-emails



<Snippet file="enterprise-feature.mdx" />

You can add your own mail server to Activepieces, or override it if it's in the cloud. From the platform, all email templates are automatically whitelabeled according to the [appearance settings](https://www.activepieces.com/docs/platform/appearance).

![Manage SMTP](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/manage-smtp.png)


# Manage AI Providers
Source: https://www.activepieces.com/docs/admin-console/manage-ai-providers



Set your AI providers so your users enjoy a seamless building experience with our universal AI pieces like [Text AI](https://www.activepieces.com/pieces/text-ai).

## Manage AI Providers

You can manage the AI providers that you want to use in your flows. To do this, go to the **AI** page in the **Admin Console**.

You can define the provider's base URL and the API key.

These settings will be used for all the projects for every request to the AI provider.

![Manage AI Providers](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/configure-ai-provider.png)

## Configure AI Credits Limits Per Project

You can configure the token limits per project. To do this, go to the project general settings and change the **AI Credits** field to the desired value.

<Note>
  This limit is per project and is an accumulation of all the reported usage by the AI piece in the project.
  Since only the AI piece goes through the Activepieces API,
  using any other piece like the standalone OpenAI, Anthropic or Perplexity pieces will not count towards or respect this limit.
</Note>

![Manage AI Providers](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/ai-credits-limit.png)

### AI Credits Explained

AI credits are the number tasks that can be run by any of our universal AI pieces.

So if you have a flow run that contains 5 universal AI pieces steps, the AI credits consumed will be 5.


# Replace OAuth2 Apps
Source: https://www.activepieces.com/docs/admin-console/manage-oauth2



<Snippet file="enterprise-feature.mdx" />

The project automatically uses Activepieces OAuth2 Apps as the default setting. If you prefer to use your own OAuth2 Apps, you can click on the 'Gear Icon' on the piece from the 'Manage Pieces' page and enter your own OAuth2 Apps details.

![Manage Oauth2 apps](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/manage-oauth2.png)


# Manage Pieces
Source: https://www.activepieces.com/docs/admin-console/manage-pieces



<Snippet file="enterprise-feature.mdx" />

## Customize Pieces for Each Project

In each **project settings** you can customize the pieces for the project.

![Manage Projects](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/manage-pieces.png)

## Install Piece

You can install custom pieces for all your projects by clicking on "Install Piece" and then filling in the piece package information.
You can choose to install it from npm or upload a tar file directly for private pieces.

![Manage Projects](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/install-piece.png)


# Managed Projects
Source: https://www.activepieces.com/docs/admin-console/manage-projects



<Snippet file="enterprise-feature.mdx" />

This feature helps you unlock these use cases:

1. Set up projects for different teams inside the company.
2. Set up projects automatically using the embedding feature for your SaaS customers.

You can **create** new projects and sets **limits** on the number of tasks for each project.


# Manage Templates
Source: https://www.activepieces.com/docs/admin-console/manage-templates



<Snippet file="enterprise-feature.mdx" />

You can create custom templates for your users within the Platform dashboard's.

<video controls autoplay muted loop playsinline className="w-full aspect-video" src="https://cdn.activepieces.com/videos/showcase/templates.mp4" />


# Overview
Source: https://www.activepieces.com/docs/admin-console/overview



<Snippet file="enterprise-feature.mdx" />

The platform is the admin panel for managing your instance. It's suitable for SaaS, Embed, or agencies that want to white-label Activepieces and offer it to their customers. With this platform, you can:

1. **Custom Branding:** Tailor the appearance of the software to align with your brand's identity by selecting your own branding colors and fonts.

2. **Projects Management:** Manage your projects, including creating, editing, and deleting projects.

3. **Piece Management:** Take full control over Activepieces pieces. You can show or hide existing pieces and create your own unique pieces to customize the platform according to your specific needs.

4. **User Authentication Management:** adding and removing users, and assigning roles to users.

5. **Template Management:** Control prebuilt templates and add your own unique templates to meet the requirements of your users.

6. **AI Provider Management:** Manage the AI providers that you want to use in your flows.


# Create Action
Source: https://www.activepieces.com/docs/developers/building-pieces/create-action



## Action Definition

Now let's create first action which fetch random ice-cream flavor.

```bash
npm run cli actions create
```

You will be asked three questions to define your new piece:

1. `Piece Folder Name`: This is the name associated with the folder where the action resides. It helps organize and categorize actions within the piece.
2. `Action Display Name`: The name users see in the interface, conveying the action's purpose clearly.
3. `Action Description`: A brief, informative text in the UI, guiding users about the action's function and purpose.
   Next, Let's create the action file:

**Example:**

```bash
npm run cli actions create

? Enter the piece folder name : gelato
? Enter the action display name : get icecream flavor
? Enter the action description : fetches random icecream flavor.
```

This will create a new TypeScript file named `get-icecream-flavor.ts` in the `packages/pieces/community/gelato/src/lib/actions` directory.

Inside this file, paste the following code:

```typescript
import {
  createAction,
  Property,
  PieceAuth,
} from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { gelatoAuth } from '../..';

export const getIcecreamFlavor = createAction({
  name: 'get_icecream_flavor', // Must be a unique across the piece, this shouldn't be changed.
  auth: gelatoAuth,
  displayName: 'Get Icecream Flavor',
  description: 'Fetches random icecream flavor',
  props: {},
  async run(context) {
    const res = await httpClient.sendRequest<string[]>({
      method: HttpMethod.GET,
      url: 'https://cloud.activepieces.com/api/v1/webhooks/RGjv57ex3RAHOgs0YK6Ja/sync',
      headers: {
        Authorization: context.auth, // Pass API key in headers
      },
    });
    return res.body;
  },
});
```

The createAction function takes an object with several properties, including the `name`, `displayName`, `description`, `props`, and `run` function of the action.

The `name` property is a unique identifier for the action. The `displayName` and `description` properties are used to provide a human-readable name and description for the action.

The `props` property is an object that defines the properties that the action requires from the user. In this case, the action doesn't require any properties.

The `run` function is the function that is called when the action is executed. It takes a single argument, context, which contains the values of the action's properties.

The `run` function utilizes the httpClient.sendRequest function to make a GET request, fetching a random ice cream flavor. It incorporates API key authentication in the request headers. Finally, it returns the response body.

## Expose The Definition

To make the action readable by Activepieces, add it to the array of actions in the piece definition.

```typescript
import { createPiece } from '@activepieces/pieces-framework';
// Don't forget to add the following import.
import { getIcecreamFlavor } from './lib/actions/get-icecream-flavor';

export const gelato = createPiece({
  displayName: 'Gelato',
  logoUrl: 'https://cdn.activepieces.com/pieces/gelato.png',
  authors: [],
  auth: gelatoAuth,
  // Add the action here.
  actions: [getIcecreamFlavor], // <--------
  triggers: [],
});
```

# Testing

By default, the development setup only builds specific components. Open the file `packages/server/api/.env` and include "gelato" in the `AP_DEV_PIECES`.

For more details, check out the [Piece Development](../development-setup/getting-started) section.

Once you edit the environment variable, restart the backend. The piece will be rebuilt. After this process, you'll need to **refresh** the frontend to see the changes.

<Tip>
  If the build fails, try debugging by running `npx nx run-many -t build --projects=gelato`.
  It will display any errors in your code.
</Tip>

To test the action, use the flow builder in Activepieces. It should function as shown in the screenshot.

![Gelato Action](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/gelato-action.png)


# Create Trigger
Source: https://www.activepieces.com/docs/developers/building-pieces/create-trigger



This tutorial will guide you through the process of creating trigger for a Gelato piece that fetches new icecream flavor.

## Trigger Definition

To create trigger run the following command,

```bash
npm run cli triggers create
```

1. `Piece Folder Name`: This is the name associated with the folder where the trigger resides. It helps organize and categorize triggers within the piece.
2. `Trigger Display Name`: The name users see in the interface, conveying the trigger's purpose clearly.
3. `Trigger Description`: A brief, informative text in the UI, guiding users about the trigger's function and purpose.
4. `Trigger Technique`: Specifies the trigger type - either [polling](../piece-reference/triggers/polling-trigger) or [webhook](../piece-reference/triggers/webhook-trigger).

**Example:**

```bash
npm run cli triggers create

? Enter the piece folder name : gelato
? Enter the trigger display name : new flavor created
? Enter the trigger description : triggers when a new icecream flavor is created.
? Select the trigger technique: polling
```

This will create a new TypeScript file at `packages/pieces/community/gelato/src/lib/triggers` named `new-flavor-created.ts`.

Inside this file, paste the following code:

```ts
import { gelatoAuth } from '../../';
import {
  DedupeStrategy,
  HttpMethod,
  HttpRequest,
  Polling,
  httpClient,
  pollingHelper,
} from '@activepieces/pieces-common';
import {
  PiecePropValueSchema,
  TriggerStrategy,
  createTrigger,
} from '@activepieces/pieces-framework';
import dayjs from 'dayjs';

const polling: Polling<
  PiecePropValueSchema<typeof gelatoAuth>,
  Record<string, never>
> = {
  strategy: DedupeStrategy.TIMEBASED,
  items: async ({ auth, propsValue, lastFetchEpochMS }) => {
    const request: HttpRequest = {
      method: HttpMethod.GET,
      url: 'https://cloud.activepieces.com/api/v1/webhooks/aHlEaNLc6vcF1nY2XJ2ed/sync',
      headers: {
        authorization: auth,
      },
    };
    const res = await httpClient.sendRequest(request);
    return res.body['flavors'].map((flavor: string) => ({
      epochMilliSeconds: dayjs().valueOf(),
      data: flavor,
    }));
  },
};

export const newFlavorCreated = createTrigger({
  auth: gelatoAuth,
  name: 'newFlavorCreated',
  displayName: 'new flavor created',
  description: 'triggers when a new icecream flavor is created.',
  props: {},
  sampleData: {},
  type: TriggerStrategy.POLLING,
  async test(context) {
    return await pollingHelper.test(polling, context);
  },
  async onEnable(context) {
    const { store, auth, propsValue } = context;
    await pollingHelper.onEnable(polling, { store, auth, propsValue });
  },

  async onDisable(context) {
    const { store, auth, propsValue } = context;
    await pollingHelper.onDisable(polling, { store, auth, propsValue });
  },

  async run(context) {
    return await pollingHelper.poll(polling, context);
  },
});
```

The way polling triggers usually work is as follows:

`Run`:The run method executes every 5 minutes, fetching data from the endpoint within a specified timestamp range or continuing until it identifies the last item ID. It then returns the new items as an array. In this example, the httpClient.sendRequest method is utilized to retrieve new flavors, which are subsequently stored in the store along with a timestamp.

## Expose The Definition

To make the trigger readable by Activepieces, add it to the array of triggers in the piece definition.

```typescript
import { createPiece } from '@activepieces/pieces-framework';
import { getIcecreamFlavor } from './lib/actions/get-icecream-flavor';
// Don't forget to add the following import.
import { newFlavorCreated } from './lib/triggers/new-flavor-created';

export const gelato = createPiece({
  displayName: 'Gelato Tutorial',
  logoUrl: 'https://cdn.activepieces.com/pieces/gelato.png',
  authors: [],
  auth: gelatoAuth,
  actions: [getIcecreamFlavor],
  // Add the trigger here.
  triggers: [newFlavorCreated], // <--------
});
```

# Testing

By default, the development setup only builds specific components. Open the file `packages/server/api/.env` and include "gelato" in the `AP_DEV_PIECES`.

For more details, check out the [Piece Development](../development-setup/getting-started) section.

Once you edit the environment variable, restart the backend. The piece will be rebuilt. After this process, you'll need to **refresh** the frontend to see the changes.

To test the trigger, use the load sample data from flow builder in Activepieces. It should function as shown in the screenshot.

![Gelato Action](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/gelato-trigger.png)


# Overview
Source: https://www.activepieces.com/docs/developers/building-pieces/overview

This section helps developers build and contribute pieces.

Building pieces is fun and important; it allows you to customize Activepieces for your own needs.

<Tip>
  We love contributions! In fact, most of the pieces are contributed by the community. Feel free to open a pull request.
</Tip>

<Tip>
  **Friendly Tip:**
  For the fastest support, we recommend joining our Discord community. We are dedicated to addressing every question and concern raised there.
</Tip>

<CardGroup cols={2}>
  <Card title="Code with TypeScript" icon="code">
    Build pieces using TypeScript for a more powerful and flexible development process.
  </Card>

  <Card title="Hot Reloading" icon="cloud-bolt">
    See your changes in the browser within 7 seconds.
  </Card>

  <Card title="Open Source" icon="earth-americas">
    Work within the open-source environment, explore, and contribute to other pieces.
  </Card>

  <Card title="Community Support" icon="people">
    Join our large community, where you can ask questions, share ideas, and develop alongside others.
  </Card>

  <Card title="Unified AI SDK" icon="brain">
    Use the Unified SDK to quickly build AI-powered pieces that support multiple AI providers.
  </Card>
</CardGroup>


# Add Piece Authentication
Source: https://www.activepieces.com/docs/developers/building-pieces/piece-authentication



### Piece Authentication

Activepieces supports multiple forms of authentication, you can check those forms [here](../piece-reference/authentication)

Now, let's establish authentication for this piece, which necessitates the inclusion of an API Key in the headers.

Modify `src/index.ts` file to add authentication,

```ts
import { PieceAuth, createPiece } from '@activepieces/pieces-framework';

export const gelatoAuth = PieceAuth.SecretText({
  displayName: 'API Key',
  required: true,
  description: 'Please use **test-key** as value for API Key',
});

export const gelato = createPiece({
  displayName: 'Gelato',
  logoUrl: 'https://cdn.activepieces.com/pieces/gelato.png',
  auth: gelatoAuth,
  authors: [],
  actions: [],
  triggers: [],
});
```

<Note>
  Use the value **test-key** as the API key when testing actions or triggers for
  Gelato.
</Note>


# Create Piece Definition
Source: https://www.activepieces.com/docs/developers/building-pieces/piece-definition



This tutorial will guide you through the process of creating a Gelato piece with an action that fetches random icecream flavor and trigger that fetches new icecream flavor created. It assumes that you are familiar with the following:

* [Activepieces Local development](../development-setup/local) Or [GitHub Codespaces](../development-setup/codespaces).
* TypeScript syntax.

## Piece Definition

To get started, let's generate a new piece for Gelato

```bash
npm run cli pieces create
```

You will be asked three questions to define your new piece:

1. `Piece Name`: Specify a name for your piece. This name uniquely identifies your piece within the ActivePieces ecosystem.
2. `Package Name`: Optionally, you can enter a name for the npm package associated with your piece. If left blank, the default name will be used.
3. `Piece Type`: Choose the piece type based on your intention. It can be either "custom" if it's a tailored solution for your needs, or "community" if it's designed to be shared and used by the broader community.

**Example:**

```bash
npm run cli pieces create

? Enter the piece name: gelato
? Enter the package name: @activepieces/piece-gelato
? Select the piece type: community
```

The piece will be generated at `packages/pieces/community/gelato/`,
the `src/index.ts` file should contain the following code

```ts
import { PieceAuth, createPiece } from '@activepieces/pieces-framework';

export const gelato = createPiece({
  displayName: 'Gelato',
  logoUrl: 'https://cdn.activepieces.com/pieces/gelato.png',
  auth: PieceAuth.None(),
  authors: [],
  actions: [],
  triggers: [],
});
```


# Fork Repository
Source: https://www.activepieces.com/docs/developers/building-pieces/setup-fork



To start building pieces, we need to fork the repository that contains the framework library and the development environment. Later, we will publish these pieces as `npm` artifacts.

Follow these steps to fork the repository:

1. Go to the repository page at [https://github.com/activepieces/activepieces](https://github.com/activepieces/activepieces).
2. Click the `Fork` button located in the top right corner of the page.

![Fork Repository](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/fork-repository.jpg)

<Tip>
  If you are an enterprise customer and want to use the private pieces feature, you can refer to the tutorial on how to set up a [private fork](../misc/private-fork).
</Tip>


# Start Building
Source: https://www.activepieces.com/docs/developers/building-pieces/start-building



This section guides you in creating a Gelato piece, from setting up your development environment to contributing the piece. By the end of this tutorial, you will have a piece with an action that fetches a random ice cream flavor and a trigger that fetches newly created ice cream flavors.

<Info>
  These are the next sections. In each step, we will do one small thing. This tutorial should take around 30 minutes.
</Info>

## Steps Overview

<Steps>
  <Step title="Fork Repository" icon="code-branch">
    Fork the repository to create your own copy of the codebase.
  </Step>

  <Step title="Setup Development Environment" icon="code">
    Set up your development environment with the necessary tools and dependencies.
  </Step>

  <Step title="Create Piece Definition" icon="gear">
    Define the structure and behavior of your Gelato piece.
  </Step>

  <Step title="Add Piece Authentication" icon="lock">
    Implement authentication mechanisms for your Gelato piece.
  </Step>

  <Step title="Create Action" icon="ice-cream">
    Create an action that fetches a random ice cream flavor.
  </Step>

  <Step title="Create Trigger" icon="ice-cream">
    Create a trigger that fetches newly created ice cream flavors.
  </Step>

  <Step title="Sharing Pieces" icon="share">
    Share your Gelato piece with others.
  </Step>
</Steps>

<Card title="Contribution" icon="gift" iconType="duotone" color="#6e41e2">
  Contribute a piece to our repo and receive +1,400 tasks/month on [Activepieces Cloud](https://cloud.activepieces.com).
</Card>


# GitHub Codespaces
Source: https://www.activepieces.com/docs/developers/development-setup/codespaces



GitHub Codespaces is a cloud development platform that enables developers to write, run, and debug code directly in their browsers, seamlessly integrated with GitHub.

### Steps to setup Codespaces

1. Go to [Activepieces repo](https://github.com/activepieces/activepieces).

2. Click Code `<>`, then under codespaces click create codespace on main.

![Create Codespace](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/development-setup_codespaces.png)

<Note>
  By default, the development setup only builds specific pieces.Open the file
  `packages/server/api/.env` and add comma-separated list of pieces to make
  available.

  For more details, check out the [Piece Development](/developers/development-setup/getting-started) section.
</Note>

3. Open the terminal and run `npm start`

4. Access the frontend URL by opening port 4200 and signing in with these details:

Email: `dev@ap.com`
Password: `12345678`


# Dev Containers
Source: https://www.activepieces.com/docs/developers/development-setup/dev-container



## Using Dev Containers in Visual Studio Code

The project includes a dev container configuration that allows you to use Visual Studio Code's [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) extension to develop the project in a consistent environment. This can be especially helpful if you are new to the project or if you have a different environment setup on your local machine.

## Prerequisites

Before you can use the dev container, you will need to install the following:

* [Visual Studio Code](https://code.visualstudio.com/).
* The [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) extension for Visual Studio Code.
* [Docker](https://www.docker.com/).

## Using the Dev Container

To use the dev container for the Activepieces project, follow these steps:

1. Clone the Activepieces repository to your local machine.
2. Open the project in Visual Studio Code.
3. Press `Ctrl+Shift+P` and type `> Dev Containers: Reopen in Container`.
4. Run `npm start`.
5. The backend will run at `localhost:3000` and the frontend will run at `localhost:4200`.

<Note>
  By default, the development setup only builds specific pieces.Open the file
  `packages/server/api/.env` and add comma-separated list of pieces to make
  available.

  For more details, check out the [Piece Development](/developers/development-setup/getting-started) section.
</Note>

The login credentials are:\
Email: `dev@ap.com`
Password: `12345678`

## Exiting the Dev Container

To exit the dev container and return to your local environment, follow these steps:

1. In the bottom left corner of Visual Studio Code, click the `Remote-Containers: Reopen folder locally` button.
2. Visual Studio Code will close the connection to the dev container and reopen the project in your local environment.

## Troubleshoot

One of the best trouble shoot after an error occur is to reset the dev container.

1. Exit the dev container
2. Run the following
   ```sh
   sh tools/reset-dev.sh
   ```
3. Rebuild the dev container from above steps


# Getting Started
Source: https://www.activepieces.com/docs/developers/development-setup/getting-started



## Development Setup

To set up the development environment, you can choose one of the following methods:

* **Codespaces**: This is the quickest way to set up the development environment. Follow the [Codespaces](./codespaces) guide.
* **Local Environment**: It is recommended for local development. Follow the [Local Environment](./local) guide.
* **Dev Container**: This method is suitable for remote development on another machine. Follow the [Dev Container](./dev-container) guide.

## Pieces Development

To avoid making the dev environment slow, not all pieces are functional during development at first. By default, only these pieces are functional at first, as specified in `AP_DEV_PIECES`.

[https://github.com/activepieces/activepieces/blob/main/packages/server/api/.env#L4](https://github.com/activepieces/activepieces/blob/main/packages/server/api/.env#L4)

To override the default list available at first, define an `AP_DEV_PIECES` environment variable with a comma-separated list of pieces to make available. For example, to make `google-sheets` and `cal-com` available, you can use:

```sh
AP_DEV_PIECES=google-sheets,cal-com npm start
```


# Local Dev Environment
Source: https://www.activepieces.com/docs/developers/development-setup/local



## Prerequisites

* Node.js v18+
* npm v9+

## Instructions

1. Setup the environment

```bash
node tools/setup-dev.js
```

2. Start the environment

This command will start activepieces with sqlite3 and in memory queue.

```bash
npm start
```

<Note>
  By default, the development setup only builds specific pieces.Open the file
  `packages/server/api/.env` and add comma-separated list of pieces to make
  available.

  For more details, check out the [Piece Development](/developers/development-setup/getting-started) section.
</Note>

3. Go to ***localhost:4200*** on your web browser and sign in with these details:

Email: `dev@ap.com`
Password: `12345678`


# Build Custom Pieces
Source: https://www.activepieces.com/docs/developers/misc/build-piece



You can use the CLI to build custom pieces for the platform. This process compiles the pieces and exports them as a `.tgz` packed archive.

### How It Works

The CLI scans the `packages/pieces/` directory for the specified piece. It checks the **name** in the `package.json` file. If the piece is found, it builds and packages it into a `.tgz` archive.

### Usage

To build a piece, follow these steps:

1. Ensure you have the CLI installed by cloning the repository.
2. Run the following command:

```bash
npm run build-piece
```

You will be prompted to enter the name of the piece you want to build. For example:

```bash
? Enter the piece folder name : google-drive
```

The CLI will build the piece and you will be given the path to the archive. For example:

```bash
Piece 'google-drive' built and packed successfully at dist/packages/pieces/community/google-drive
```


# Create New AI Provider
Source: https://www.activepieces.com/docs/developers/misc/create-new-ai-provider



ActivePieces currently supports the following AI providers:

* OpenAI
* Anthropic

To create a new AI provider, you need to follow these steps:

## Implement the AI Interface

Create a new factory that returns an instance of the `AI` interface in the `packages/pieces/community/common/src/lib/ai/providers/your-ai-provider.ts` file.

```typescript
export const yourAiProvider = ({
  serverUrl,
  engineToken,
}: { serverUrl: string, engineToken: string }): AI<YourAiProviderSDK> => {
  const impl = new YourAiProviderSDK(serverUrl, engineToken);
  return {
    provider: "YOUR_AI_PROVIDER" as const,
    chat: {
      text: async (params) => {
        try {
          const response = await impl.chat.text(params);
          return response;
        } catch (e: any) {
          if (e?.error?.error) {
            throw e.error.error;
          }
          throw e;
        }
      }
    },
  };
};
```

## Register the AI Provider

Add the new AI provider to the `AiProviders` enum in `packages/pieces/community/common/src/lib/ai/providers/index.ts` file.

```diff
export const AiProviders = [
+  {
+    logoUrl: 'https://cdn.activepieces.com/pieces/openai.png',
+    defaultBaseUrl: 'https://api.your-ai-provider.com',
+    label: 'Your AI Provider' as const,
+    value: 'your-ai-provider' as const,
+    models: [
+      { label: 'model-1', value: 'model-1' },
+      { label: 'model-2', value: 'model-2' },
+      { label: 'model-3', value: 'model-3' },
+    ],
+    factory: yourAiProvider,
+  },
...
]
```

## Define Authentication Header

Now we need to tell ActivePieces how to authenticate to your AI provider. You can do this by adding an `auth` property to the `AiProvider` object.

The `auth` property is an object that defines the authentication mechanism for your AI provider. It consists of two properties: `name` and `mapper`. The `name` property specifies the name of the header that will be used to authenticate with your AI provider, and the `mapper` property defines a function that maps the value of the header to the format that your AI provider expects.

Here's an example of how to define the authentication header for a bearer token:

```diff
export const AiProviders = [
  {
    logoUrl: 'https://cdn.activepieces.com/pieces/openai.png',
    defaultBaseUrl: 'https://api.your-ai-provider.com',
    label: 'Your AI Provider' as const,
    value: 'your-ai-provider' as const,
    models: [
      { label: 'model-1', value: 'model-1' },
      { label: 'model-2', value: 'model-2' },
      { label: 'model-3', value: 'model-3' },
    ],
+    auth: authHeader({ bearer: true }), // or authHeader({ name: 'x-api-key', bearer: false })
    factory: yourAiProvider,
  },
...
]
```

## Test the AI Provider

To test the AI provider, you can use a **universal AI** piece in a flow. Follow these steps:

* Add the required headers from the admin console for the newly created AI provider. These headers will be used to authenticate the requests to the AI provider.

![Configure AI Provider](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/configure-ai-provider.png)

* Create a flow that uses our **universal AI** pieces. And select **"Your AI Provider"** as the AI provider in the **Ask AI** action settings.

![Configure AI Provider](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/use-ai-provider.png)


# Custom Pieces CI/CD
Source: https://www.activepieces.com/docs/developers/misc/pieces-ci-cd



You can use the CLI to sync custom pieces. There is no need to rebuild the Docker image as they are loaded directly from npm.

### How It Works

Use the CLI to sync items from `packages/pieces/custom/` to instances. In production, Activepieces acts as an npm registry, storing all piece versions.

The CLI scans the directory for `package.json` files, checking the **name** and **version** of each piece. If a piece isn't uploaded, it packages and uploads it via the API.

### Usage

To use the CLI, follow these steps:

1. Generate an API Key from the Admin Interface. Go to Settings and generate the API Key.
2. Install the CLI by cloning the repository.
3. Run the following command, replacing `API_KEY` with your generated API Key and `INSTANCE_URL` with your instance URL:

```bash
AP_API_KEY=your_api_key_here npm run sync-pieces -- --apiUrl https://INSTANCE_URL/api
```

### Developer Workflow

1. Developers create and modify the pieces offline.
2. Increment the piece version in their corresponding `package.json`. For more information, refer to the [piece versioning](../../developers/piece-reference/piece-versioning) documentation.
3. Open a pull request towards the main branch.
4. Once the pull request is merged to the main branch, manually run the CLI or use a GitHub/GitLab Action to trigger the synchronization process.

### GitHub Action

```yaml
name: Sync Custom Pieces

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  sync-pieces:
    runs-on: ubuntu-latest

    steps:
      # Step 1: Check out the repository code with full history
      - name: Check out repository code
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      # Step 2: Cache Node.js dependencies
      - name: Cache Node.js dependencies
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: npm-${{ hashFiles('package-lock.json') }}
          restore-keys: |
            npm-

      # Step 3: Set up Node.js
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20' # Use Node.js version 20
          cache: 'npm'

      # Step 4: Install dependencies using npm ci
      - name: Install dependencies
        run: npm ci --ignore-scripts

      # Step 6: Sync Custom Pieces
      - name: Sync Custom Pieces
        env:
          AP_API_KEY: ${{ secrets.AP_API_KEY }}
        run: npm run sync-pieces -- --apiUrl ${{ secrets.INSTANCE_URL }}/api

```


# Setup Private Fork
Source: https://www.activepieces.com/docs/developers/misc/private-fork



<Tip>
  **Friendly Tip #1:** If you want to experiment, you can fork or clone the public repository.
</Tip>

<Tip>
  For private piece installation, you will need the paid edition. However, you can still develop pieces, contribute them back, **OR** publish them to the public npm registry and use them in your own instance or project.
</Tip>

## Create a Private Fork (Private Pieces)

By following these steps, you can create a private fork on GitHub, GitLab or another platform and configure the "activepieces" repository as the upstream source, allowing you to incorporate changes from the "activepieces" repository.

1. **Clone the Repository:**

Begin by creating a bare clone of the repository. Remember that this is a temporary step and will be deleted later.

```bash
git clone --bare git@github.com:activepieces/activepieces.git
```

2. **Create a Private Git Repository**

Generate a new private repository on GitHub or your chosen platform. When initializing the new repository, do not include a README, license, or gitignore files. This precaution is essential to avoid merge conflicts when synchronizing your fork with the original repository.

3. **Mirror-Push to the Private Repository:**

Mirror-push the bare clone you created earlier to your newly created "activepieces" repository. Make sure to replace `<your_username>` in the URL below with your actual GitHub username.

```bash
cd activepieces.git
git push --mirror git@github.com:<your_username>/activepieces.git
```

4. **Remove the Temporary Local Repository:**

```bash
cd ..
rm -rf activepieces.git
```

5. **Clone Your Private Repository:**

Now, you can clone your "activepieces" repository onto your local machine into your desired directory.

```bash
cd ~/path/to/directory
git clone git@github.com:<your_username>/activepieces.git
```

6. **Add the Original Repository as a Remote:**

If desired, you can add the original repository as a remote to fetch potential future changes. However, remember to disable push operations for this remote, as you are not permitted to push changes to it.

```bash
git remote add upstream git@github.com:activepieces/activepieces.git
git remote set-url --push upstream DISABLE
```

You can view a list of all your remotes using `git remote -v`. It should resemble the following:

```
origin	git@github.com:<your_username>/activepieces.git (fetch)
origin	git@github.com:<your_username>/activepieces.git (push)
upstream	git@github.com:activepieces/activepieces.git (fetch)
upstream	DISABLE (push)
```

> When pushing changes, always use `git push origin`.

### Sync Your Fork

To retrieve changes from the "upstream" repository, fetch the remote and rebase your work on top of it.

```bash
git fetch upstream
git merge upstream/main
```

Conflict resolution should not be necessary since you've only added pieces to your repository.


# Publish Custom Pieces
Source: https://www.activepieces.com/docs/developers/misc/publish-piece



You can use the CLI to publish custom pieces to the platform. This process packages the pieces and uploads them to the specified API endpoint.

### How It Works

The CLI scans the `packages/pieces/` directory for the specified piece. It checks the **name** and **version** in the `package.json` file. If the piece is not already published, it builds, packages, and uploads it to the platform using the API.

### Usage

To publish a piece, follow these steps:

1. Ensure you have an API Key. Generate it from the Admin Interface by navigating to Settings.
2. Install the CLI by cloning the repository.
3. Run the following command:

```bash
npm run publish-piece-to-api
```

4. You will be asked three questions to publish your piece:

* `Piece Folder Name`: This is the name associated with the folder where the action resides. It helps organize and categorize actions within the piece.

* `API URL`: This is the URL of the API endpoint where the piece will be published (ex: [https://cloud.activepieces.com/api](https://cloud.activepieces.com/api)).

* `API Key Source`: This is the source of the API key. It can be either `Env Variable (AP_API_KEY)` or `Manually`.

In case you choose `Env Variable (AP_API_KEY)`, the CLI will use the API key from the `.env` file in the `packages/server/api` directory.

In case you choose `Manually`, you will be asked to enter the API key.

Examples:

```bash
npm run publish-piece-to-api

? Enter the piece folder name : google-drive
? Enter the API URL : https://cloud.activepieces.com/api
? Enter the API Key Source : Env Variable (AP_API_KEY)

```

```bash
npm run publish-piece-to-api

? Enter the piece folder name : google-drive
? Enter the API URL : https://cloud.activepieces.com/api
? Enter the API Key Source : Manually
? Enter the API Key : ap_1234567890abcdef1234567890abcdef

```


# Piece Auth
Source: https://www.activepieces.com/docs/developers/piece-reference/authentication

Learn about piece authentication

Piece authentication is used to gather user credentials and securely store them for future use in different flows. The authentication must be defined as the `auth` parameter in the `createPiece`, `createTrigger`, and `createAction` functions.

This requirement ensures that the type of authentication can be inferred correctly in triggers and actions.

<Tip>
  Friendly Tip: Only at most one authentication is allowed per piece.
</Tip>

### Secret Text

This authentication collects sensitive information, such as passwords or API keys. It is displayed as a masked input field.

**Example:**

```typescript
PieceAuth.SecretText({
    displayName: 'API Key',
    description: 'Enter your API key',
    required: true,
    // Optional Validation
    validate: async ({auth}) => {
        if(auth.startsWith('sk_')){
            return {
                valid: true,
            }
        }
        return {
            valid: false,
            error: 'Invalid Api Key'
        }
    }
})
```

### Username and Password

This authentication collects a username and password as separate fields.

**Example:**

```typescript
PieceAuth.BasicAuth({
    displayName: 'Credentials',
    description: 'Enter your username and password',
    required: true,
    username: {
        displayName: 'Username',
        description: 'Enter your username',
    },
    password: {
        displayName: 'Password',
        description: 'Enter your password',
    },
    // Optional Validation
    validate: async ({auth}) => {
        if(auth){
            return {
                valid: true,
            }
        }
        return {
            valid: false,
            error: 'Invalid Api Key'
        }
    }
})
```

### Custom

This authentication allows for custom authentication by collecting specific properties, such as a base URL and access token.

**Example:**

```typescript
PieceAuth.CustomAuth({
    displayName: 'Custom Authentication',
    description: 'Enter custom authentication details',
    props: {
        base_url: Property.ShortText({
            displayName: 'Base URL',
            description: 'Enter the base URL',
            required: true,
        }),
        access_token: PieceAuth.SecretText({
            displayName: 'Access Token',
            description: 'Enter the access token',
            required: true
        })
    },
    // Optional Validation
    validate: async ({auth}) => {
        if(auth){
            return {
                valid: true,
            }
        }
        return {
            valid: false,
            error: 'Invalid Api Key'
        }
    },
    required: true
})
```

### OAuth2

This authentication collects OAuth2 authentication details, including the authentication URL, token URL, and scope.

**Example:**

```typescript
PieceAuth.OAuth2({
    displayName: 'OAuth2 Authentication',
    grantType: OAuth2GrantType.AUTHORIZATION_CODE,
    required: true,
    authUrl: 'https://example.com/auth',
    tokenUrl: 'https://example.com/token',
    scope: ['read', 'write']
})
```

<Tip>
  Please note `OAuth2GrantType.CLIENT_CREDENTIALS` is also supported for service-based authentication.
</Tip>


# Enable Custom API Calls
Source: https://www.activepieces.com/docs/developers/piece-reference/custom-api-calls

Learn how to enable custom API calls for your pieces

Custom API Calls allow the user to send a request to a specific endpoint if no action has been implemented for it.

This will show in the actions list of the piece as `Custom API Call`, to enable this action for a piece, you need to call the `createCustomApiCallAction` in your actions array.

## Basic Example

The example below implements the action for the OpenAI piece. The OpenAI piece uses a `Bearer token` authorization header to identify the user sending the request.

```typescript
actions: [
  ...yourActions,
  createCustomApiCallAction({
    // The auth object defined in the piece
    auth: openaiAuth,
    // The base URL for the API
    baseUrl: () => {
      'https://api.openai.com/v1'
    },
    // Mapping the auth object to the needed authorization headers
    authMapping: async (auth) => {
      return {
        'Authorization': `Bearer ${auth}`
      }
    }
  })
]
```

## Dynamic Base URL and Basic Auth Example

The example below implements the action for the Jira Cloud piece. The Jira Cloud piece uses a dynamic base URL for it's actions, where the base URL changes based on the values the user authenticated with. We will also implement a Basic authentication header.

```typescript
actions: [
  ...yourActions,
  createCustomApiCallAction({
    baseUrl: (auth) => {
      return `${(auth as JiraAuth).instanceUrl}/rest/api/3`
    },
    auth: jiraCloudAuth,
    authMapping: async (auth) => {
      const typedAuth = auth  as JiraAuth
      return {
        'Authorization': `Basic ${typedAuth.email}:${typedAuth.apiToken}`
      }
    }
  })
]
```


# Piece Examples
Source: https://www.activepieces.com/docs/developers/piece-reference/examples

Explore a collection of example triggers and actions

To get the full benefit, it is recommended to read the tutorial first.

## Triggers:

**Webhooks:**

* [New Form Submission on Typeform](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/typeform/src/lib/trigger/new-submission.ts)

**Polling:**

* [New Completed Task On Todoist](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/todoist/src/lib/triggers/task-completed-trigger.ts)

## Actions:

* [Send a message On Discord](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/discord/src/lib/actions/send-message-webhook.ts)
* [Send an mail On Gmail](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/gmail/src/lib/actions/send-email-action.ts)

## Authentication

**OAuth2:**

* [Slack](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/slack/src/index.ts)
* [Gmail](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/gmail/src/index.ts)

**API Key:**

* [Sendgrid](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/sendgrid/src/index.ts)

**Basic Authentication:**

* [Twilio](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/twilio/src/index.ts)


# External Libraries
Source: https://www.activepieces.com/docs/developers/piece-reference/external-libraries

Learn how to install and use external libraries.

The Activepieces repository is structured as a monorepo, employing Nx as its build tool.

To use an external library in your project, you can simply add it to the main `package.json` file and then use it in any part of your project.

Nx will automatically detect where you're using the library and include it in the build.

Here's how to install and use an external library:

* Install the library using:

```bash
npm install --save <library-name>
```

* Import the library into your piece.

Guidelines:

* Make sure you are using well-maintained libraries.
* Ensure that the library size is not too large to avoid bloating the bundle size; this will make the piece load faster in the sandbox.


# Files
Source: https://www.activepieces.com/docs/developers/piece-reference/files

Learn how to use files object to create file references.

The `ctx.files` object allow you to store files in local storage or in a remote storage depending on the run environment.

## Write

You can use the `write` method to write a file to the storage, It returns a string that can be used in other actions or triggers properties to reference the file.

**Example:**

```ts
const fileReference = await files.write({
    fileName: 'file.txt',
    data: Buffer.from('text')
});
```

<Tip>
  This code will store the file in the database If the run environment is testing mode since it will be required to test other steps, other wise it will store it in the local temporary directory.
</Tip>

For Reading the file If you are using the file property in a trigger or action, It will be automatically parsed and you can use it directly, please refer to `Property.File` in the [properties](./properties#file) section.


# Flow Control
Source: https://www.activepieces.com/docs/developers/piece-reference/flow-control

Learn How to Control Flow from Inside the Piece

Flow Controls provide the ability to control the flow of execution from inside a piece. By using the `ctx` parameter in the `run` method of actions, you can perform various operations to control the flow.

## Stop Flow

You can stop the flow and provide a response to the webhook trigger. This can be useful when you want to terminate the execution of the piece and send a specific response back.

**Example with Response:**

```typescript
context.run.stop({
  response: {
    status: context.propsValue.status ?? StatusCodes.OK,
    body: context.propsValue.body,
    headers: (context.propsValue.headers as Record<string, string>) ?? {},
  },
});
```

**Example without Response:**

```typescript
context.run.stop();
```

## Pause Flow and Wait for Webhook

You can pause flow and return HTTP response, also provide a callback to URL that you can call with certain payload and continue the flow.

**Example:**

```typescript
ctx.run.pause({
  pauseMetadata: {
    type: PauseType.WEBHOOK,
    response: {
      callbackUrl: context.generateResumeUrl({
        queryParams: {},
      }),
    },
  },
});
```

## Pause Flow and Delay

You can pause or delay the flow until a specific timestamp. Currently, the only supported type of pause is a delay based on a future timestamp.

**Example:**

```typescript
ctx.run.pause({
    pauseMetadata: {
        type: PauseType.DELAY,
        resumeDateTime: futureTime.toUTCString()
    }
});
```

These flow hooks give you control over the execution of the piece by allowing you to stop the flow or pause it until a certain condition is met. You can use these hooks to customize the behavior and flow of your actions.


# Persistent Storage
Source: https://www.activepieces.com/docs/developers/piece-reference/persistent-storage

Learn how to store and retrieve data from a key-value store

The `ctx` parameter inside triggers and actions provides a simple key/value storage mechanism. The storage is persistent, meaning that the stored values are retained even after the execution of the piece.

By default, the storage operates at the flow level, but it can also be configured to store values at the project level.

<Tip>
  The storage scope is completely isolated. If a key is stored in a different scope, it will not be fetched when requested in different scope.
</Tip>

## Put

You can store a value with a specified key in the storage.

**Example:**

```typescript
ctx.store.put('KEY', 'VALUE', StoreScope.PROJECT);
```

## Get

You can retrieve the value associated with a specific key from the storage.

**Example:**

```typescript
const value = ctx.store.get<string>('KEY', StoreScope.PROJECT);
```

## Delete

You can delete a key-value pair from the storage.

**Example:**

```typescript
ctx.store.delete('KEY', StoreScope.PROJECT);
```

These storage operations allow you to store, retrieve, and delete key-value pairs in the persistent storage. You can use this storage mechanism to store and retrieve data as needed within your triggers and actions.


# Piece Versioning
Source: https://www.activepieces.com/docs/developers/piece-reference/piece-versioning

Learn how to version your pieces

Pieces are npm packages and follows **semantic versioning**.

## Semantic Versioning

The version number consists of three numbers: `MAJOR.MINOR.PATCH`, where:

* **MAJOR** It should be incremented when there are breaking changes to the piece.
* **MINOR** It should be incremented for new features or functionality that is compatible with the previous version, unless the major version is less than 1.0, in which case it can be a breaking change.
* **PATCH** It should be incremented for bug fixes and small changes that do not introduce new features or break backward compatibility.

## Engine

The engine will use the most up-to-date compatible version for a given piece version during the **DRAFT** flow versions. Once the flow is published, all pieces will be locked to a specific version.

**Case 1: Piece Version is Less Than 1.0**:
The engine will select the latest **patch** version that shares the same **minor** version number.

**Case 2: Piece Version Reaches Version 1.0**:
The engine will select the latest **minor** version that shares the same **major** version number.

## Examples

<Tip>
  when you make a change, remember to increment the version accordingly.
</Tip>

### Breaking changes

* Remove an existing action.
* Add a required `action` prop.
* Remove an existing action prop, whether required or optional.
* Remove an attribute from an action output.
* Change the existing behavior of an action/trigger.

### Non-breaking changes

* Add a new action.
* Add an optional `action` prop.
* Add an attribute to an action output.

i.e., any removal is breaking, any required addition is breaking, everything else is not breaking.


# Props
Source: https://www.activepieces.com/docs/developers/piece-reference/properties

Learn about different types of properties used in triggers / actions

Properties are used in actions and triggers to collect information from the user. They are also displayed to the user for input. Here are some commonly used properties:

## Basic Properties

These properties collect basic information from the user.

### Short Text

This property collects a short text input from the user.

**Example:**

```typescript
Property.ShortText({
  displayName: 'Name',
  description: 'Enter your name',
  required: true,
  defaultValue: 'John Doe',
});
```

### Long Text

This property collects a long text input from the user.

**Example:**

```typescript
Property.LongText({
  displayName: 'Description',
  description: 'Enter a description',
  required: false,
});
```

### Checkbox

This property presents a checkbox for the user to select or deselect.

**Example:**

```typescript
Property.Checkbox({
  displayName: 'Agree to Terms',
  description: 'Check this box to agree to the terms',
  required: true,
  defaultValue: false,
});
```

### Markdown

This property displays a markdown snippet to the user, useful for documentation or instructions. It includes a `variant` option to style the markdown, using the `MarkdownVariant` enum:

* **BORDERLESS**: For a minimalistic, no-border layout.
* **INFO**: Displays informational messages.
* **WARNING**: Alerts the user to cautionary information.
* **TIP**: Highlights helpful tips or suggestions.

The default value for `variant` is **INFO**.

**Example:**

```typescript
Property.MarkDown({
    value: '## This is a markdown snippet',
    variant: MarkdownVariant.WARNING,
}),
```

<Tip>
  If you want to show a webhook url to the user, use `{{ webhookUrl }}` in the
  markdown snippet.
</Tip>

### DateTime

This property collects a date and time from the user.

**Example:**

```typescript
Property.DateTime({
  displayName: 'Date and Time',
  description: 'Select a date and time',
  required: true,
  defaultValue: '2023-06-09T12:00:00Z',
});
```

### Number

This property collects a numeric input from the user.

**Example:**

```typescript
Property.Number({
  displayName: 'Quantity',
  description: 'Enter a number',
  required: true,
});
```

### Static Dropdown

This property presents a dropdown menu with predefined options.

**Example:**

```typescript
Property.StaticDropdown({
  displayName: 'Country',
  description: 'Select your country',
  required: true,
  options: {
    options: [
      {
        label: 'Option One',

        value: '1',
      },
      {
        label: 'Option Two',
        value: '2',
      },
    ],
  },
});
```

### Static Multiple Dropdown

This property presents a dropdown menu with multiple selection options.

**Example:**

```typescript
Property.StaticMultiSelectDropdown({
  displayName: 'Colors',
  description: 'Select one or more colors',
  required: true,
  options: {
    options: [
      {
        label: 'Red',
        value: 'red',
      },
      {
        label: 'Green',
        value: 'green',
      },
      {
        label: 'Blue',
        value: 'blue',
      },
    ],
  },
});
```

### JSON

This property collects JSON data from the user.

**Example:**

```typescript
Property.Json({
  displayName: 'Data',
  description: 'Enter JSON data',
  required: true,
  defaultValue: { key: 'value' },
});
```

### Dictionary

This property collects key-value pairs from the user.

**Example:**

```typescript
Property.Object({
  displayName: 'Options',
  description: 'Enter key-value pairs',
  required: true,
  defaultValue: {
    key1: 'value1',
    key2: 'value2',
  },
});
```

### File

This property collects a file from the user, either by providing a URL or uploading a file.

**Example:**

```typescript
Property.File({
  displayName: 'File',
  description: 'Upload a file',
  required: true,
});
```

### Array of Strings

This property collects an array of strings from the user.

**Example:**

```typescript
Property.Array({
  displayName: 'Tags',
  description: 'Enter tags',
  required: false,
  defaultValue: ['tag1', 'tag2'],
});
```

### Array of Fields

This property collects an array of objects from the user.

**Example:**

```typescript
Property.Array({
  displayName: 'Fields',
  description: 'Enter fields',
  properties: {
    fieldName: Property.ShortText({
      displayName: 'Field Name',
      required: true,
    }),
    fieldType: Property.StaticDropdown({
      displayName: 'Field Type',
      required: true,
      options: {
        options: [
          { label: 'TEXT', value: 'TEXT' },
          { label: 'NUMBER', value: 'NUMBER' },
        ],
      },
    }),
  },
  required: false,
  defaultValue: [],
});
```

## Dynamic Data Properties

These properties provide more advanced options for collecting user input.

### Dropdown

This property allows for dynamically loaded options based on the user's input.

**Example:**

```typescript
Property.Dropdown({
  displayName: 'Options',
  description: 'Select an option',
  required: true,
  refreshers: ['auth'],
  refreshOnSearch: false,
  options: async ({ auth }, { searchValue }) => {
    // Search value only works when refreshOnSearch is true
    if (!auth) {
      return {
        disabled: true,
      };
    }
    return {
      options: [
        {
          label: 'Option One',
          value: '1',
        },
        {
          label: 'Option Two',
          value: '2',
        },
      ],
    };
  },
});
```

<Tip>
  When accessing the Piece auth, be sure to use exactly `auth` as it is
  hardcoded. However, for other properties, use their respective names.
</Tip>

### Multi-Select Dropdown

This property allows for multiple selections from dynamically loaded options.

**Example:**

```typescript
Property.MultiSelectDropdown({
  displayName: 'Options',
  description: 'Select one or more options',
  required: true,
  refreshers: ['auth'],
  options: async ({ auth }) => {
    if (!auth) {
      return {
        disabled: true,
      };
    }
    return {
      options: [
        {
          label: 'Option One',
          value: '1',
        },
        {
          label: 'Option Two',
          value: '2',
        },
      ],
    };
  },
});
```

<Tip>
  When accessing the Piece auth, be sure to use exactly `auth` as it is
  hardcoded. However, for other properties, use their respective names.
</Tip>

### Dynamic Properties

This property is used to construct forms dynamically based on API responses or user input.

**Example:**

```typescript
Property.DynamicProperties({
  description: 'Dynamic Form',
  displayName: 'Dynamic Form',
  required: true,
  refreshers: ['authentication'],
  props: async (propsValue) => {
    const authentication = propsValue['authentication'];
    const apiEndpoint = 'https://someapi.com';
    const response = await fetch(apiEndpoint);
    const data = await response.json();

    const properties = {
      prop1: Property.ShortText({
        displayName: 'Property 1',
        description: 'Enter property 1',
        required: true,
      }),
      prop2: Property.Number({
        displayName: 'Property 2',
        description: 'Enter property 2',
        required: false,
      }),
    };

    return properties;
  },
});
```

### Custom Property (BETA)

<Warning>
  This feature is still in BETA and not fully released yet, please let us know if you use it and face any issues and consider it a possibility could have breaking changes in the future
</Warning>

This is a property that basically lets you inject JS code into the frontend and manipulate the DOM of this content however you like.
It has a "code" property which is your JS script, it should be a function that takes in an object parameter which will have the following schema:

```typescript
{
        //the container in which you will add your html, you can use tailwind to stylize your template
        containerId,
        value,
        onChange,
        //in case you want to hide your property for embedding.
        isEmbedded,
        projectId,
        disabled
}
```

here is how to define such a property:

```typescript
 Property.Custom({
      code: `
      (params) => {
        const containerId = params.containerId;
        const label = document.createElement('div');
        label.textContent = 'Hello from custom property';
        const labelClasses = 'text-sm font-medium text-gray-900'.split(' ');
        label.classList.add(...labelClasses);
        const container = document.getElementById(containerId);
        container.appendChild(label);
        container.appendChild(button);
        const containerClasses = 'flex items-center justify-between'.split(' ');
        container.classList.add(...containerClasses);
        const input = document.createElement('input');
        const inputClassList = 'border border-solid border-border rounded-md'.split(' ');
        input.classList.add(...inputClassList)
        input.type = 'text';
        input.value = params.value?? "Default value";
        input.oninput = (e) => {
          console.log("input changed", e.target.value);
          params.onChange(e.target.value);
        }
        container.appendChild(input);
      }`,
      displayName: 'Custom Property',
      required: true,
      defaultValue: "Default Value", 
      description: "Custom Property Made By You",
    })
```


# Props Validation
Source: https://www.activepieces.com/docs/developers/piece-reference/properties-validation

Learn about different types of properties validation 

Activepieces uses Zod for runtime validation of piece properties. Zod provides a powerful schema validation system that helps ensure your piece receives valid inputs.

To use Zod validation in your piece, first import the validation helper and Zod:

<Warning>
  Please make sure the `minimumSupportedRelease` is set to at least `0.36.1` for the validation to work.
</Warning>

```typescript
import { createAction, Property } from '@activepieces/pieces-framework';
import { propsValidation } from '@activepieces/pieces-common';
import { z } from 'zod';

export const getIcecreamFlavor = createAction({
  name: 'get_icecream_flavor', // Unique name for the action.
  displayName: 'Get Ice Cream Flavor',
  description: 'Fetches a random ice cream flavor based on user preferences.',
  props: {
    sweetnessLevel: Property.Number({
      displayName: 'Sweetness Level',
      required: true,
      description: 'Specify the sweetness level (0 to 10).',
    }),
    includeToppings: Property.Checkbox({
      displayName: 'Include Toppings',
      required: false,
      description: 'Should the flavor include toppings?',
      defaultValue: true,
    }),
    numberOfFlavors: Property.Number({
      displayName: 'Number of Flavors',
      required: true,
      description: 'How many flavors do you want to fetch? (1-5)',
      defaultValue: 1,
    }),
  },
  async run({ propsValue }) {
    // Validate the input properties using Zod
    await propsValidation.validateZod(propsValue, {
      sweetnessLevel: z.number().min(0).max(10, 'Sweetness level must be between 0 and 10.'),
      numberOfFlavors: z.number().min(1).max(5, 'You can fetch between 1 and 5 flavors.'),
    });

    // Action logic
    const sweetnessLevel = propsValue.sweetnessLevel;
    const includeToppings = propsValue.includeToppings ?? true; // Default to true
    const numberOfFlavors = propsValue.numberOfFlavors;

    // Simulate fetching random ice cream flavors
    const allFlavors = [
      'Vanilla',
      'Chocolate',
      'Strawberry',
      'Mint',
      'Cookie Dough',
      'Pistachio',
      'Mango',
      'Coffee',
      'Salted Caramel',
      'Blackberry',
    ];
    const selectedFlavors = allFlavors.slice(0, numberOfFlavors);

    return {
      message: `Here are your ${numberOfFlavors} flavors: ${selectedFlavors.join(', ')}`,
      sweetnessLevel: sweetnessLevel,
      includeToppings: includeToppings,
    };
  },
});

```


# Overview
Source: https://www.activepieces.com/docs/developers/piece-reference/triggers/overview



This tutorial explains three techniques for creating triggers:

* `Polling`: Periodically call endpoints to check for changes.
* `Webhooks`: Listen to user events through a single URL.
* `App Webhooks (Subscriptions)`: Use a developer app (using OAuth2) to receive all authorized user events at a single URL (Not Supported).

to create new trigger run following command,

```bash
npm run cli triggers create
```

1. `Piece Folder Name`: This is the name associated with the folder where the trigger resides. It helps organize and categorize triggers within the piece.
2. `Trigger Display Name`: The name users see in the interface, conveying the trigger's purpose clearly.
3. `Trigger Description`: A brief, informative text in the UI, guiding users about the trigger's function and purpose.
4. `Trigger Technique`: Specifies the trigger type - either polling or webhook.

# Trigger Structure

```typescript
export const createNewIssue = createTrigger({
    auth: PieceAuth | undefined
    name: string, // Unique name across the piece.
    displayName: string, // Display name on the interface.
	description: string, // Description for the action
    triggerType: POLLING | WEBHOOK,

    props: {}; // Required properties from the user.
    // Run when the user enable or publish the flow.

	onEnable: (ctx) => {};
    // Run when the user disable the flow or
    // the old flow is deleted after new one is published.
	onDisable: (ctx) => {};

    // Trigger implementation, It takes context as parameter.
    // should returns an array of payload, each payload considered
    // a separate flow run.
    run: async run(ctx): unknown[] => {}
})
```

<Tip>
  It's important to note that the `run` method returns an array. The reason for
  this is that a single polling can contain multiple triggers, so each item in
  the array will trigger the flow to run.
</Tip>

## Context Object

The Context object contains multiple helpful pieces of information and tools that can be useful while developing.

```typescript
// Store: A simple, lightweight key-value store that is helpful when you are developing triggers that persist between runs, used to store information like the last polling date.
await context.store.put('_lastFetchedDate', new Date());
const lastFetchedData = await context.store.get('_lastFetchedDate', new Date());

// Webhook URL: A unique, auto-generated URL that will trigger the flow. Useful when you need to develop a trigger based on webhooks.
context.webhookUrl;

// Payload: Contains information about the HTTP request sent by the third party. It has three properties: status, headers, and body.
context.payload;

// PropsValue: Contains the information filled by the user in defined properties.
context.propsValue;
```

**App Webhooks (Not Supported)**

Certain services, such as `Slack` and `Square`, only support webhooks at the developer app level.
This means that all authorized users for the app will be sent to the same endpoint. While this technique will be supported soon, for now, a workaround is to perform polling on the endpoint.


# Polling Trigger
Source: https://www.activepieces.com/docs/developers/piece-reference/triggers/polling-trigger

Periodically call endpoints to check for changes

The way polling triggers usually work is as follows:

**On Enable:**
Store the last timestamp or most recent item id using the context store property.

**Run:**
This method runs every **5 minutes**, fetches the endpoint between a certain timestamp or traverses until it finds the last item id, and returns the new items as an array.

**Testing:**
You can implement a test function which should return some of the most recent items. It's recommended to limit this to five.

**Examples:**

* [New Record Airtable](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/airtable/src/lib/trigger/new-record.trigger.ts)
* [New Updated Item Salesforce](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/salesforce/src/lib/trigger/new-updated-record.ts)

# Polling library

There multiple strategy to implement polling triggers, and we have created a library to help you with that.

## Strategies

**Timebased:**

This strategy fetches new items using a timestamp. You need to implement the items method, which should return the most recent items.
The library will detect new items based on the timestamp.

The polling object's generic type consists of the props value and the object type.

```typescript
const polling: Polling<{ authentication: OAuth2PropertyValue, object: string }> = {
  strategy: DedupeStrategy.TIMEBASED,
  items: async ({ propsValue, lastFetchEpochMS }) => {
    // Todo implement the logic to fetch the items
    const items = [ {id: 1, created_date: '2021-01-01T00:00:00Z'}, {id: 2, created_date: '2021-01-01T00:00:00Z'}];
    return items.map((item) => ({
      epochMilliSeconds: dayjs(item.created_date).valueOf(),
      data: item,
    }));
  }
}
```

**Last ID Strategy:**

This strategy fetches new items based on the last item ID. To use this strategy, you need to implement the items method, which should return the most recent items.
The library will detect new items after the last item ID.

The polling object's generic type consists of the props value and the object type

```typescript
const polling: Polling<{ authentication: AuthProps}> = {
    strategy: DedupeStrategy.LAST_ITEM,
    items: async ({ propsValue }) => {
        // Implement the logic to fetch the items
        const items = [{ id: 1 }, { id: 2 }];
        return items.map((item) => ({
            id: item.id,
            data: item,
        }));
    }
}
```

## Trigger Implementation

After implementing the polling object, you can use the polling helper to implement the trigger.

```typescript
export const newTicketInView = createTrigger({
    name: 'new_ticket_in_view',
    displayName: 'New ticket in view',
    description: 'Triggers when a new ticket is created in a view',
    type: TriggerStrategy.POLLING,
    props: {
        authentication: Property.SecretText({
            displayName: 'Authentication',
            description: markdownProperty,
            required: true,
        }),
    },
    sampleData: {},
    onEnable: async (context) => {
        await pollingHelper.onEnable(polling, {
            store: context.store,
            propsValue: context.propsValue,
            auth: context.auth
        })
    },
    onDisable: async (context) => {
        await pollingHelper.onDisable(polling, {
            store: context.store,
            propsValue: context.propsValue,
            auth: context.auth

        })
    },
    run: async (context) => {
        return await pollingHelper.poll(polling, context);
    },
    test: async (context) => {
        return await pollingHelper.test(polling, context);
    }
});
```


# Webhook Trigger
Source: https://www.activepieces.com/docs/developers/piece-reference/triggers/webhook-trigger

Listen to user events through a single URL

The way webhook triggers usually work is as follows:

**On Enable:**
Use `context.webhookUrl` to perform an HTTP request to register the webhook in a third-party app, and store the webhook Id in the `store`.

**On Handshake:**
Some services require a successful handshake request usually consisting of some challenge. It works similar to a normal run except that you return the correct challenge response. This is optional and in order to enable the handshake you need to configure one of the available handshake strategies in the `handshakeConfiguration` option.

**Run:**
You can find the HTTP body inside `context.payload.body`. If needed, alter the body; otherwise, return an array with a single item `context.payload.body`.

**Disable:**
Using the `context.store`, fetch the webhook ID from the enable step and delete the webhook on the third-party app.

**Testing:**
You cannot test it with Test Flow, as it uses static sample data provided in the piece.
To test the trigger, publish the flow, perform the event. Then check the flow runs from the main dashboard.

**Examples:**

* [New Form Submission on Typeform](https://github.com/activepieces/activepieces/blob/main/packages/pieces/community/typeform/src/lib/trigger/new-submission.ts)

<Warning>
  To make your webhook accessible from the internet, you need to configure the backend URL. Follow these steps:

  1. Install ngrok.
  2. Run the command `ngrok http 4200`.
  3. Replace the `AP_FRONTEND_URL` environment variable in `packages/server/api/.env` with the ngrok URL.

  Once you have completed these configurations, you are good to go!
</Warning>


# Community (Public NPM)
Source: https://www.activepieces.com/docs/developers/sharing-pieces/community

Learn how to publish your piece to the community.

You can publish your pieces to the npm registry and share them with the community. Users can install your piece from Settings -> My Pieces -> Install Piece -> type in the name of your piece package.

<Steps>
  <Step title="Login to npm">
    Make sure you are logged in to npm. If not, please run:

    ```bash
    npm login
    ```
  </Step>

  <Step title="Rename Piece">
    Rename the piece name in `package.json` to something unique or related to your organization's scope (e.g., `@my-org/piece-PIECE_NAME`). You can find it at `packages/pieces/PIECE_NAME/package.json`.

    <Tip>
      Don't forget to increase the version number in `package.json` for each new release.
    </Tip>
  </Step>

  <Step title="Publish">
    <Tip>
      Replace `PIECE_FOLDER_NAME` with the name of the folder.
    </Tip>

    Run the following command:

    ```bash
    npm run publish-piece PIECE_FOLDER_NAME
    ```
  </Step>
</Steps>

**Congratulations! You can now import the piece from the settings page.**


# Contribute
Source: https://www.activepieces.com/docs/developers/sharing-pieces/contribute

Learn how to contribute a piece to the main repository.

<Steps>
  <Step title="Open a pull request">
    * Build and test your piece.
    * Open a pull request from your repository to the main fork.
    * A maintainer will review your work closely.
  </Step>

  <Step title="Merge the pull request">
    * Once the pull request is approved, it will be merged into the main branch.
    * Your piece will be available within a few minutes.
    * An automatic GitHub action will package it and create an npm package on npmjs.com.
  </Step>
</Steps>


# Overview
Source: https://www.activepieces.com/docs/developers/sharing-pieces/overview

Learn the different ways to publish your own piece on activepieces.

## Methods

* [Contribute Back](/developers/sharing-pieces/contribute): Publish your piece by contributing back your piece to main repository.
* [Community](/developers/sharing-pieces/community): Publish your piece on npm directly and share it with the community.
* [Private](/developers/sharing-pieces/private): Publish your piece on activepieces privately.


# Private
Source: https://www.activepieces.com/docs/developers/sharing-pieces/private

Learn how to share your pieces privately.

<Snippet file="enterprise-feature.mdx" />

This guide assumes you have already created a piece and created a private fork of our repository, and you would like to package it as a file and upload it.

<Tip>
  Friendly Tip: There is a CLI to easily upload it to your platform. Please check out [Publish Custom Pieces](../misc/publish-piece).
</Tip>

<Steps>
  <Step title="Build Piece">
    Build the piece using the following command. Make sure to replace `${name}` with your piece name.

    ```bash
    npm run pieces -- build --name=${name}
    ```

    <Info>
      More information about building pieces can be found [here](../misc/build-piece).
    </Info>
  </Step>

  <Step title="Upload Tarball">
    Upload the generated tarball inside `dist/packages/pieces/${name}`from Activepieces Platform Admin -> Pieces

    ![Manage Pieces](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/install-piece.png)
  </Step>
</Steps>


# Chat Completion
Source: https://www.activepieces.com/docs/developers/unified-ai/chat

Learn how to use chat completion AI in actions

The following snippet shows how to use chat completion to get a response from an AI model.

```typescript
const ai = AI({ provider: context.propsValue.provider, server: context.server });

const response = await ai.chat.text({
  model: context.propsValue.model,
  messages: [
    {
      role: AIChatRole.USER,
      content: "Can you provide examples of TypeScript code formatting?",
    },
  ],
  /**
   * Controls the creativity of the AI response.
   * A higher value will make the AI more creative and a lower value will make it more deterministic.
   */
  creativity: 0.7,
  /**
   * The maximum number of tokens to generate in the completion.
   */
  maxTokens: 100,
});
```


# Function Calling
Source: https://www.activepieces.com/docs/developers/unified-ai/function-calling

Learn how to use function calling AI in actions

### Chat-based Function Calling

The code snippet below shows how to use a function call to extract structured data directly from a text input:

```typescript
const chatResponse = await ai.chat.function({
    model: context.propsValue.model,
    messages: [
        {
            role: AIChatRole.USER,
            content: context.propsValue.text,
        },
    ],
    functions: [
        {
            name: 'extract_structured_data',
            description: 'Extract the following data from the provided text.',
            arguments: [
                { name: 'customerName', type: 'string', description: 'The customer\'s name.', isRequired: true },
                { name: 'orderId', type: 'string', description: 'Unique order identifier.', isRequired: true },
                { name: 'purchaseDate', type: 'string', description: 'Date of purchase (YYYY-MM-DD).', isRequired: false },
                { name: 'totalAmount', type: 'number', description: 'Total transaction amount in dollars.', isRequired: false },
            ],
        }
    ]
});
```

### Image-based Function Calling

To extract structured data from an image, use this function call:

```typescript
const imageResponse = await ai.image.function({
    model: context.propsValue.imageModel,
    image: context.propsValue.imageData,
    functions: [
        {
            name: 'extract_structured_data',
            description: 'Extract the following data from the image text.',
            arguments: [
                { name: 'customerName', type: 'string', description: 'The customer\'s name.', isRequired: true },
                { name: 'orderId', type: 'string', description: 'Unique order identifier.', isRequired: true },
                { name: 'purchaseDate', type: 'string', description: 'Date of purchase (YYYY-MM-DD).', isRequired: false },
                { name: 'totalAmount', type: 'number', description: 'Total transaction amount in dollars.', isRequired: false },
            ],
        }
    ]
});
```


# Image AI
Source: https://www.activepieces.com/docs/developers/unified-ai/image

Learn how to use image AI in actions

The following snippet shows how to use image generation to create an image using AI.

```typescript
const ai = AI({
  provider: context.propsValue.provider,
  server: context.server,
});

const response = await image.generate({
  // The model to use for image generation
  model: context.propsValue.model,
  // The prompt to guide the image generation
  prompt: context.propsValue.prompt,
  // The resolution of the generated image
  size: "1024x1024",
  // Any advanced options for the image generation
  advancedOptions: {},
});

```


# Overview
Source: https://www.activepieces.com/docs/developers/unified-ai/overview

The AI Toolkit to build AI pieces tailored for specific use cases that work with many AI providers

**What it provides:**

* 🔐 **Centralized Credentials Management**: Admin manages credentials, end users use without hassle.
* 🌐 **Support for Multiple AI Providers**: OpenAI, Anthropic, Google, LLAMA, and many open-source models.
* 💬 **Support for Various AI Capabilities**: Chat, 🖼️ Image, 🎤 Voice, and more.

![Unified AI SDK](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/unified-ai.png)

## Getting Started


# Customize Pieces
Source: https://www.activepieces.com/docs/embedding/customize-pieces



<Snippet file="enterprise-feature.mdx" />

This documentation explains how to customize access to pieces depending on projects.

<Steps>
  <Step title="Tag Pieces">
    You can tag pieces in bulk using **Admin Console**

    ![Bulk Tag](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/tag-pieces.png)
  </Step>

  <Step title="Add Tags to Provision Token">
    We need to specify the tags of pieces in the token, check how to generate token in [provision-users](./provision-users).

    You should specify the `pieces` claim like this:

    ```json
    {
        /// Other claims
        "piecesFilterType": "ALLOWED",
        "piecesTags": [ "free" ]
    }
    ```

    Each time the token is used in the frontend, it will sync all pieces with these tags to the project.
    The project's pieces list will **exactly match** all pieces with these tags at the moment of using the iframe.
  </Step>
</Steps>


# Embed Builder
Source: https://www.activepieces.com/docs/embedding/embed-builder



<Snippet file="enterprise-feature.mdx" />

This documentation explains how to embed the Activepieces iframe inside your application and customize it.

## Configure SDK

Adding the embedding SDK script will initialize an object in your window called `activepieces`, which has a method called `configure` that you should call after the container has been rendered.

<Tip>
  The following scripts shouldn't contain the `async` or `defer` attributes.
</Tip>

<Tip>
  These steps assume you have already generated a JWT token from the backend. If not, please check the [provision-users](./provision-users) page.
</Tip>

```html
<script src="https://cdn.activepieces.com/sdk/embed/0.3.5.js">
</script>
<script>
activepieces.configure({
  prefix: "/",
  instanceUrl: 'INSTANCE_URL',
  jwtToken: "GENERATED_JWT_TOKEN",
  embedding: {
    containerId: "container",
    builder: {
      disableNavigation: false,
      hideLogo: false,
      hideFlowName: false
    },
    dashboard: {
      hideSidebar: false
    },
    hideFolders: false,
    navigation: {
      handler: ({ route }) => {
          // The iframe route has changed, make sure you check the navigation section.
        }
    }
  },
});

</script>
```

<Tip>
  `configure` returns a promise which is resolved after authentication is done.
</Tip>

<Tip>
  Please check the [navigation](./navigation.mdx) section, as it's very important to understand how navigation works and how to supply an auto-sync experience.
</Tip>

**Configure Parameters:**

| Parameter Name                      | Required | Type                       | Description                                                                                                                                                                                                                |
| ----------------------------------- | -------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| prefix                              | ❌        | string                     | Some customers have an embedding prefix, like this `<embedding_url_prefix>/<Activepieces_url>`. For example if the prefix is `/automation` and the Activepieces url is `/flows` the full url would be `/automation/flows`. |
| instanceUrl                         | ✅        | string                     | The url of the instance hosting Activepieces, could be [https://cloud.activepieces.com](https://cloud.activepieces.com) if you are a cloud user.                                                                           |
| jwtToken                            | ✅        | string                     | The jwt token you generated to authenticate your users to Activepieces.                                                                                                                                                    |
| embedding.containerId               | ❌        | string                     | The html element's id that is going to be containing Activepieces's iframe.                                                                                                                                                |
| embedding.builder.disableNavigation | ❌        | boolean                    | Hides the folder name and back button in the builder, by default it is false.                                                                                                                                              |
| embedding.builder.hideLogo          | ❌        | boolean                    | Hides the logo in the builder's header, by default it is false.                                                                                                                                                            |
| embedding.builder.hideFlowName      | ❌        | boolean                    | Hides the flow name and flow actions dropdown in the builder's header, by default it is false.                                                                                                                             |
| embedding.dashboard.hideSidebar     | ❌        | boolean                    | Controls the visibility of the sidebar in the dashboard, by default it is false.                                                                                                                                           |
| embedding.hideFolders               | ❌        | boolean                    | Hides all things related to folders in both the flows table and builder by default it is false.                                                                                                                            |
| embedding.styling.fontUrl           | ❌        | string                     | The url of the font to be used in the embedding, by default it is `https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap`.                                                                     |
| embedding.styling.fontFamily        | ❌        | string                     | The font family to be used in the embedding, by default it is `Roboto`.                                                                                                                                                    |
| navigation.handler                  | ❌        | `({route:string}) => void` | If defined the callback will be triggered each time a route in Activepieces changes, you can read more about it [here](/embedding/navigation)                                                                              |

<Tip>
  For the font to be loaded, you need to set both the `fontUrl` and `fontFamily` properties.
  If you only set one of them, the default font will be used.
  The default font is `Roboto`.
  The font weights we use are the default font-weights from [tailwind](https://tailwindcss.com/docs/font-weight).
</Tip>


# Create Connections
Source: https://www.activepieces.com/docs/embedding/embed-connections



<Info>
  **Requirements:**

  * Activepieces version 0.34.5 or higher
  * SDK version 0.3.2 or higher
</Info>

<Info>
  "connectionName" is the externalId of the connection (you can get it by hovering the connection name in the connections table).  <br />
  We kept the same parameter name for backward compatibility, anyone upgrading their instance from \< 0.35.1, will not face issues in that regard.
</Info>

<Warning>
  **Breaking Change**: <br /> If your Activepieces instance version is \< 0.45.0 and (you are using the connect method from the embed sdk, and need the connection externalId to be returned after the user creates it OR if you want to reconnect a specific connection with an externalId), you must upgrade your instance to >= 0.45.0
</Warning>

You can use the embedded SDK to create connections.

<Steps>
  <Step title="Initialize the SDK">
    Follow the instructions in the [Embed Builder](./embed-builder).
  </Step>

  <Step title="Call Connect Method">
    After initializing the SDK, you will have access to a property called `activepieces` inside your `window` object. Call its `connect` method to open a new connection dialog as follows.

    ```html
    <script> 
    activepieces.connect({pieceName:'@activepieces/piece-google-sheets'});
    </script>
    ```

    **Connect Parameters:**

    | Parameter Name | Required | Type                                                              | Description                                                                                                                                                                                                   |
    | -------------- | -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | pieceName      | ✅        | string                                                            | The name of the piece you want to create a connection for.                                                                                                                                                    |
    | connectionName | ❌        | string                                                            | The external Id of the connection (you can get it by hovering the connection name in the connections table), when provided the connection created/upserted will use this as the external Id and display name. |
    | newWindow      | ❌        | \{ width?: number, height?: number, top?: number, left?: number } | If set the connection dialog will be opened in a new window instead of an iframe taking the full page.                                                                                                        |

    **Connect Result**

    The `connect` method returns a `promise` that resolves to the following:

    ```ts
    {
        connection?: {
            id: string,
            name: string
        }
    }
    ```

    <Info>
      `name` is the externalId of the connection.
      `connection` is undefined if the user closes the dialog and doesn't create a connection.
    </Info>

    <Tip>
      You can use the `connections` piece in the builder to retrieve the created connection using its name.
      ![Connections in Builder](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/connections-piece.png)
      ![Connections in Builder](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/connections-piece-usage.png)
    </Tip>
  </Step>
</Steps>


# Navigation
Source: https://www.activepieces.com/docs/embedding/navigation



By default, navigating within your embedded instance of Activepieces doesn't affect the client's browser history or viewed URL. Activepieces only provide a **handler**, that trigger on every route change in the **iframe**.

## Automatically Sync URL

You can use the following snippet when configuring the SDK, which will implement a handler that syncs the Activepieces iframe with your browser:

<Tip>
  The following snippet listens when the user clicks backward, so it syncs the route back to the iframe using `activepieces.navigate` and in the handler, it updates the URL of the browser.
</Tip>

```js
activepieces.configure({
  prefix: "/",
  instanceUrl: 'INSTANCE_URL',
  jwtToken: "GENERATED_JWT_TOKEN",
  embedding: {
    containerId: "container",
    builder: {
      disableNavigation: false,
      hideLogo: false,
      hideFlowName: false
    },
    dashboard: {
      hideSidebar: false
    },
    hideFolders: false,
    navigation: {
      handler: ({ route }) => {
        //route can include search params at the end of it
        if (!window.location.href.endsWith(route)) {
          window.history.pushState({}, "", window.location.origin + route);
        }
      }
    }
  },
});

window.addEventListener("popstate", () => {
  const route = activepieces.extractActivepiecesRouteFromUrl({ vendorUrl: window.location.href });
  activepieces.navigate({ route });
});
```

## Navigate Method

If you use `activepieces.navigate({ route: '/flows' })` this will tell the embedded sdk where to navigate to.

Here is the list for routes the sdk can navigate to:

| Route               | Description                    |
| ------------------- | ------------------------------ |
| `/flows`            | Flows table                    |
| `/flows/{flowId}`   | Opens up a flow in the builder |
| `/runs`             | Runs table                     |
| `/runs/{runId}`     | Opens up a run in the builder  |
| `/connections`      | Connections table              |
| `/tables`           | Tables table                   |
| `/tables/{tableId}` | Opens up a table               |
| `todos`             | Todos table                    |
| `todos/{todoId}`    | Opens up a todo                |


# Overview
Source: https://www.activepieces.com/docs/embedding/overview

Understanding how embedding works

<Snippet file="enterprise-feature.mdx" />

This section provides an overview of how to embed the Activepieces builder in your application and automatically provision the user.

The embedding process involves the following steps:

<Steps>
  <Step title="Provision Users">
    Generate a JSON Web Token (JWT) to identify your customer and pass it to the frontend.
  </Step>

  <Step title="Embed Builder">
    Use the Activepieces SDK and the JWT to embed the Activepieces builder as an iframe, and customize using the SDK.
  </Step>
</Steps>

<Tip>
  In case, you need to gather connections in custom place in your application. You can do this with the SDK. Find more info [here](./embed-connections.mdx).
</Tip>


# Provision Users
Source: https://www.activepieces.com/docs/embedding/provision-users

Automatically authenticate your SaaS users to your Activepieces instance

<Snippet file="enterprise-feature.mdx" />

## Overview

In Activepieces, there are **Projects** and **Users**. Each project is provisioned with their corresponding workspace, project, or team in your SaaS. The users are then mapped to the respective users in Activepieces.

To achieve this, the backend will generate a signed token that contains all the necessary information to automatically create a user and project. If the user or project already exists, it will skip the creation and log in the user directly.

<Steps>
  <Step title="Step 1: Obtain Signing Key">
    You can generate a signing key by going to **Platform Settings -> Signing Keys -> Generate Signing Key**.

    This will generate a public and private key pair. The public key will be used by Activepieces to verify the signature of the JWT tokens you send. The private key will be used by you to sign the JWT tokens.

    <Warning>
      Please store your private key in a safe place, as it will not be stored in Activepieces.
    </Warning>
  </Step>

  <Step title="Step 2: Generate a JWT">
    The signing key will be used to generate JWT tokens for the currently logged-in user on your website, which will then be sent to the Activepieces Iframe as a query parameter to authenticate the user and exchange the token for a longer lived token.

    To generate these tokens, you will need to add code in your backend to generate the token using the RS256 algorithm, so the JWT header would look like this:

    <Tip>
      To obtain the `SIGNING_KEY_ID`, refer to the signing key table and locate the value in the first column.
    </Tip>

    ```json
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "SIGNING_KEY_ID"
    }
    ```

    The signed tokens must include these claims in the payload:

    ```json
    {
      "version": "v3",
      "externalUserId": "user_id",
      "externalProjectId": "user_project_id",
      "firstName": "John",
      "lastName": "Doe",
      "role": "EDITOR",
      "piecesFilterType": "NONE",
      "exp": 1856563200
    }
    ```

    | Claim             | Description                                                                            |
    | ----------------- | -------------------------------------------------------------------------------------- |
    | externalUserId    | Unique identification of the user in **your** software                                 |
    | externalProjectId | Unique identification of the user's project in **your** software                       |
    | firstName         | First name of the user                                                                 |
    | lastName          | Last name of the user                                                                  |
    | role              | Role of the user in the Activepieces project (e.g., **EDITOR**, **VIEWER**, **ADMIN**) |
    | exp               | Expiry timestamp for the token (Unix timestamp)                                        |
    | piecesFilterType  | Customize the project pieces, check [customize pieces](/embedding/customize-pieces)    |
    | piecesTags        | Customize the project pieces, check [customize pieces](/embedding/customize-pieces)    |
    | tasks             | Customize the task limit, check the section below                                      |

    You can use any JWT library to generate the token. Here is an example using the jsonwebtoken library in Node.js:

    <Tip>
      **Friendly Tip #1**: You can also use this [tool](https://dinochiesa.github.io/jwt/) to generate a quick example.
    </Tip>

    <Tip>
      **Friendly Tip #2**: Make sure the expiry time is very short, as it's a temporary token and will be exchanged for a longer-lived token.
    </Tip>

    ```javascript Node.js
    const jwt = require('jsonwebtoken');

    // JWT NumericDates specified in seconds:
    const currentTime = Math.floor(Date.now() / 1000);
    let token = jwt.sign(
      {
        version: "v3",
        externalUserId: "user_id",
        externalProjectId: "user_project_id",
        firstName: "John",
        lastName: "Doe",
        role: "EDITOR",
        piecesFilterType: "NONE",
        exp: currentTime + (60 * 60), // 1 hour from now
      },
      process.env.ACTIVEPIECES_SIGNING_KEY,
      {
        algorithm: "RS256",
        header: {
          kid: signingKeyID, // Include the "kid" in the header
        },
      }
    );
    ```

    Once you have generated the token, please check the embedding docs to know how to embed the token in the iframe.
  </Step>
</Steps>


# SDK Changelog
Source: https://www.activepieces.com/docs/embedding/sdk-changelog

A log of all notable changes to Activepieces SDK

<Warning>
  **Breaking Change**: <br /> If your Activepieces image version is \< 0.45.0 and (you are using the connect method from the embed SDk, and need the connection externalId to be returned after the user creates it OR if you want to reconnect a specific connection with an externalId), you must upgrade your instance to >= 0.45.0
</Warning>

<Warning>
  Between Acitvepieces image version 0.32.1 and 0.46.4 the navigation handler was including the project id in the path, this might have broken implementation logic for people using the navigation handler, this has been fixed from 0.46.5 and onwards, the handler won't show the project id prepended to routes.
</Warning>

### 02/24/2025 (3.0.5)

* Added a new parameter to the connect method to make the connection dialog a popup instead of an iframe taking the full page.
* Fixed a bug where the returned promise from the connect method was always resolved to \{connection: undefined}
* Now when you use the connect method with the "connectionName" parameter, the user will reconnect to the connection with the matching externalId instead of creating a new one.

### 02/04/2025 (3.0.4)

* This version requires you to update Activepieces to 0.41.0
* Adds the ability to pass font family name and font url to the embed sdk

### 01/26/2025 (3.0.3)

* This version requires you to update Activepieces to 0.39.8
* activepieces.configure method was being resolved before the user was authenticated, this is fixed now, so you can use activepieces.navigate method to navigate to your desired initial route.

### 12/04/2024 (3.0)

<Warning>
  **Breaking Change**: Automatic URL sync has been removed. Instead, Activepieces now provides a callback handler method. Please read [Embedding Navigation](./navigation) for more information.
</Warning>

* add custom navigation handler ([#4500](https://github.com/activepieces/activepieces/pull/4500))
* allow passing a predefined name for connection in connect method ([#4485](https://github.com/activepieces/activepieces/pull/4485))
* add changelog ([#4503](https://github.com/activepieces/activepieces/pull/4503))


# Delete Connection
Source: https://www.activepieces.com/docs/endpoints/connections/delete

DELETE /v1/app-connections/{id}
Delete an app connection



# List Connections
Source: https://www.activepieces.com/docs/endpoints/connections/list

GET /v1/app-connections/



# Connection Schema
Source: https://www.activepieces.com/docs/endpoints/connections/schema





# Upsert Connection
Source: https://www.activepieces.com/docs/endpoints/connections/upsert

POST /v1/app-connections
Upsert an app connection based on the app name



# Get Flow Run
Source: https://www.activepieces.com/docs/endpoints/flow-runs/get

GET /v1/flow-runs/{id}
Get Flow Run



# List Flows Runs
Source: https://www.activepieces.com/docs/endpoints/flow-runs/list

GET /v1/flow-runs
List Flow Runs



# Flow Run Schema
Source: https://www.activepieces.com/docs/endpoints/flow-runs/schema





# Create Flow Template
Source: https://www.activepieces.com/docs/endpoints/flow-templates/create

POST /v1/flow-templates
Create a flow template



# Delete Flow Template
Source: https://www.activepieces.com/docs/endpoints/flow-templates/delete

DELETE /v1/flow-templates/{id}
Delete a flow template



# Get Flow Template
Source: https://www.activepieces.com/docs/endpoints/flow-templates/get

GET /v1/flow-templates/{id}
Get a flow template



# List Flow Templates
Source: https://www.activepieces.com/docs/endpoints/flow-templates/list

GET /v1/flow-templates
List flow templates



# Flow Template Schema
Source: https://www.activepieces.com/docs/endpoints/flow-templates/schema





# Create Flow
Source: https://www.activepieces.com/docs/endpoints/flows/create

POST /v1/flows
Create a flow



# Delete Flow
Source: https://www.activepieces.com/docs/endpoints/flows/delete

DELETE /v1/flows/{id}
Delete a flow



# Get Flow
Source: https://www.activepieces.com/docs/endpoints/flows/get

GET /v1/flows/{id}
Get a flow by id



# List Flows
Source: https://www.activepieces.com/docs/endpoints/flows/list

GET /v1/flows
List flows



# Flow Schema
Source: https://www.activepieces.com/docs/endpoints/flows/schema





# Apply Flow Operation
Source: https://www.activepieces.com/docs/endpoints/flows/update

POST /v1/flows/{id}
Apply an operation to a flow



# Create Folder
Source: https://www.activepieces.com/docs/endpoints/folders/create

POST /v1/folders
Create a new folder



# Delete Folder
Source: https://www.activepieces.com/docs/endpoints/folders/delete

DELETE /v1/folders/{id}
Delete a folder



# Get Folder
Source: https://www.activepieces.com/docs/endpoints/folders/get

GET /v1/folders/{id}
Get a folder by id



# List Folders
Source: https://www.activepieces.com/docs/endpoints/folders/list

GET /v1/folders
List folders



# Folder Schema
Source: https://www.activepieces.com/docs/endpoints/folders/schema





# Update Folder
Source: https://www.activepieces.com/docs/endpoints/folders/update

POST /v1/folders/{id}
Update an existing folder



# Configure
Source: https://www.activepieces.com/docs/endpoints/git-repos/configure

POST /v1/git-repos
Upsert a git repository information for a project.



# Git Repos Schema
Source: https://www.activepieces.com/docs/endpoints/git-repos/schema





# Delete Global Connection
Source: https://www.activepieces.com/docs/endpoints/global-connections/delete

DELETE /v1/global-connections/{id}



# List Global Connections
Source: https://www.activepieces.com/docs/endpoints/global-connections/list

GET /v1/global-connections



# Global Connection Schema
Source: https://www.activepieces.com/docs/endpoints/global-connections/schema





# Update Global Connection
Source: https://www.activepieces.com/docs/endpoints/global-connections/update

POST /v1/global-connections/{id}



# Upsert Global Connection
Source: https://www.activepieces.com/docs/endpoints/global-connections/upsert

POST /v1/global-connections



# Overview
Source: https://www.activepieces.com/docs/endpoints/overview



<Tip>
  API keys are generated under the platform dashboard at this moment to manage multiple projects, which is only available in the Platform and Enterprise editions,
  Please contact [sales@activepieces.com](mailto:sales@activepieces.com) for more information.
</Tip>

### Authentication:

The API uses "API keys" to authenticate requests. You can view and manage your API keys from the Platform Dashboard. After creating the API keys, you can pass the API key as a Bearer token in the header.

Example:
`Authorization: Bearer {API_KEY}`

### Pagination

All endpoints use seek pagination, to paginate through the results, you can provide the `limit` and `cursor` as query parameters.

The API response will have the following structure:

```json
{
    "data": [],
    "next": "string",
    "previous": "string"
}
```

* **`data`**: Holds the requested results or data.

* **`next`**: Provides a starting cursor for the next set of results, if available.

* **`previous`**: Provides a starting cursor for the previous set of results, if applicable.


# Install Piece
Source: https://www.activepieces.com/docs/endpoints/pieces/install

POST /v1/pieces
Add a piece to a platform



# Piece Schema
Source: https://www.activepieces.com/docs/endpoints/pieces/schema





# Delete Project Member
Source: https://www.activepieces.com/docs/endpoints/project-members/delete

DELETE /v1/project-members/{id}



# List Project Member
Source: https://www.activepieces.com/docs/endpoints/project-members/list

GET /v1/project-members



# Project Member Schema
Source: https://www.activepieces.com/docs/endpoints/project-members/schema





# Create Project Release
Source: https://www.activepieces.com/docs/endpoints/project-releases/create

POST /v1/project-releases



# Project Release Schema
Source: https://www.activepieces.com/docs/endpoints/project-releases/schema





# Create Project
Source: https://www.activepieces.com/docs/endpoints/projects/create

POST /v1/projects



# List Projects
Source: https://www.activepieces.com/docs/endpoints/projects/list

GET /v1/projects



# Project Schema
Source: https://www.activepieces.com/docs/endpoints/projects/schema





# Update Project
Source: https://www.activepieces.com/docs/endpoints/projects/update

POST /v1/projects/{id}



# Get Sample Data
Source: https://www.activepieces.com/docs/endpoints/sample-data/get

GET /v1/sample-data



# Save Sample Data
Source: https://www.activepieces.com/docs/endpoints/sample-data/save

POST /v1/sample-data



# Delete User Invitation
Source: https://www.activepieces.com/docs/endpoints/user-invitations/delete

DELETE /v1/user-invitations/{id}



# List User Invitations
Source: https://www.activepieces.com/docs/endpoints/user-invitations/list

GET /v1/user-invitations



# User Invitation Schema
Source: https://www.activepieces.com/docs/endpoints/user-invitations/schema





# Send User Invitation (Upsert)
Source: https://www.activepieces.com/docs/endpoints/user-invitations/upsert

POST /v1/user-invitations
Send a user invitation to a user. If the user already has an invitation, the invitation will be updated.



# Building Flows
Source: https://www.activepieces.com/docs/flows/building-flows

Flow consists of two parts, trigger and actions

## Trigger

The flow's starting point determines its frequency of execution. There are various types of triggers available, such as Schedule Trigger, Webhook Trigger, or Event Trigger based on specific service.

## Action

Actions come after the flow and control what occurs when the flow is activated, like running code or communicating with other services.

In real-life scenario:

![Flow Parts](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/flow-parts.png)


# Debugging Runs
Source: https://www.activepieces.com/docs/flows/debugging-runs

Ensuring your business automations are running properly

You can monitor each run that results from an enabled flow:

1. Go to the Dashboard, click on **Runs**.
2. Find the run that you're looking for, and click on it.
3. You will see the builder in a view-only mode, each step will show a ✅ or a ❌ to indicate its execution status.
4. Click on any of these steps, you will see the **input** and **output** in the **Run Details** panel.

The debugging experience looks like this:
![Debugging Business Automations](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/using-activepieces-debugging.png)


# Technical limits
Source: https://www.activepieces.com/docs/flows/known-limits

technical limits for Activepieces execution

### Overview

<Warning>
  This Limits applies for the **Activepieces Cloud**, and can be configured via environment variables for self-hosted instances.
</Warning>

### Flow Limits

* **Execution Time**: Each flow has a maximum execution time of **600 seconds (10 minutes)**. Flows exceeding this limit will be marked as a timeout.
* **Memory Usage**: During execution, a flow should not use more than **128 MB of RAM**.

<Tip>
  **Friendly Tip #1:** Flow run in a paused state, such as Wait for Approval or Delay, do not count toward the 600 seconds.
</Tip>

<Tip>
  **Friendly Tip #2:** The execution time limit can be worked around by splitting the flows into multiple ones, such as by having one flow call another flow using a webhook, or by having each flow process a small batch of items.
</Tip>

### File Storage Limits

<Info>
  The files from actions or triggers are stored in the database / S3 to support retries from certain steps.
</Info>

* **Maximum File Size**: 10 MB

### Data Storage Limits

Some pieces utilize the built-in Activepieces key store, such as the Store Piece and Queue Piece.

The storage limits are as follows:

* **Maximum Key Length**: 128 characters
* **Maximum Value Size**: 512 KB


# Passing Data
Source: https://www.activepieces.com/docs/flows/passing-data

Using data from previous steps in the current one

## Data flow

Any Activepieces flow is a vertical diagram that **starts with a trigger step** followed by **any number of action steps**.

Steps are connected vertically. Data flows from parent steps to the children. Children steps have access to the output data of the parent steps.

## Example Steps

<video width="450" autoPlay muted loop playsinline src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-3steps.mp4" />

This flow has 3 steps, they can access data as follows:

* **Step 1** is the main data producer to be used in the next steps. Data produced by Step 1 will be accessible in Steps 2 and 3. Some triggers don't produce data though, like Schedules.

* **Step 2** can access data produced by Step 1. After execution, this step will also produce data to be used in the next step(s).

* **Step 3** can access data produced by Steps 1 and 2 as they're its parent steps. This step can produce data but since it's the last step in the flow, it can't be used by other ones.

## Data to Insert Panel

In order to use data from a previous step in your current step, place your cursor in any input, the **Data to Insert** panel will pop up.

<video autoPlay muted loop playsinline src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-data-to-insert-panel.mp4" />

This panel shows the accessible steps and their data. You can expand the data items to view their content, and you can click the items to insert them in your current settings input.

If an item in this panel has a caret (⌄) to the right, it means you can click on the item to expand its child properties. You can select the parent item or its properties as you need.

When you insert data from this panel, it gets inserted at the cursor's position in the input. This means you can combine static text and dynamic data in any field.

<video autoPlay muted loop playsinline src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-main-insert-data-example.mp4" />

We generally recommend that you expand the items before inserting them to understand the type of data they contain and whether they're the right fit to the input you're filling.

## Testing Steps to Generate Data

We require you to test steps before accessing their data. This approach protects you from selecting the wrong data and breaking your flows after publishing them.

If a step is not tested and you try to access its data, you will see the following message:

<img width="350" src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-test-step-first.png" alt="Test your automation step first" />

To fix this, go to the step and use the Generate Sample Data panel to test it. Steps use different approaches for testing. These are the common ones:

* **Load Data:** Some triggers will let you load data from your connected account without having to perform any action in that account.
* **Test Trigger:** Some triggers will require you to head to your connected account and fire the trigger in order to generate sample data.
* **Send Data:** Webhooks require you to send a sample request to the webhook URL to generate sample data.
* **Test Action:** Action steps will let you run the action in order to generate sample data.

Follow the instructions in the Generate Sample Data panel to know how your step should be tested. Some triggers will also let you Use Mock Data, which will generate static sample data from the piece. We recommend that you test the step instead of using mock data.

This is an example for generating sample data for a trigger using the **Load Data** button:

<video autoPlay muted loop playsinline src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-load-data.mp4" />

## Advanced Tips

### Switching to Dynamic Values

Dropdowns and some other input types don't let you select data from previous steps. If you'd like to bypass this and use data from previous steps instead, switch the input into a dynamic one using this button:

<video autoPlay muted loop playsinline src="https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/passing-data-dynamic-value.mp4" />

### Accessing data by path

If you can't find the data you're looking for in the **Data to Insert** panel but you'd like to use it, you can write a JSON path instead.

Use the following syntax to write JSON paths:

`{{step_slug.path.to.property}}`

The `step_slug` can be found by moving your cursor over any of your flow steps, it will show to the right of the step.


# Publishing Flows
Source: https://www.activepieces.com/docs/flows/publishing-flows

Make your flow work by publishing your updates

The changes you make won't work right away to avoid disrupting the flow that's already published. To enable your changes, simply click on the publish button once you're done with your changes.

![Flow Parts](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/publish-flow.png)


# Version History
Source: https://www.activepieces.com/docs/flows/versioning

Learn how flow versioning works in Activepieces

Activepieces keeps track of all published flows and their versions. Here’s how it works:

1. You can edit a flow as many times as you want in **draft** mode.
2. Once you're done with your changes, you can publish it.
3. The published flow will be **immutable** and cannot be edited.
4. If you try to edit a published flow, Activepieces will create a new **draft** if there is none and copy the **published** version to the new version.

This means you can always go back to a previous version and edit the flow in draft mode without affecting the published version.

![Flow History](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/flow-history.png)

As you can see in the following screenshot, the yellow dot refers to DRAFT and the green dot refers to PUBLISHED.


# 🥳 Welcome to Activepieces
Source: https://www.activepieces.com/docs/getting-started/introduction

Your friendliest open source all-in-one automation tool, designed to be extensible.

<CardGroup cols={2}>
  <Card href="/flows/building-flows" title="Learn Concepts" icon="shapes" color="#8143E3">
    Learn how to work with Activepieces
  </Card>

  <Card href="https://www.activepieces.com/pieces" title="Pieces" icon="puzzle-piece" color="#8143E3">
    Browse available pieces
  </Card>

  <Card href="/install/overview" title="Install" icon="server" color="#8143E3">
    Learn how to install Activepieces
  </Card>

  <Card href="/developers/building-pieces/overview" title="Developers" icon="code" color="#8143E3">
    How to Build Pieces and Contribute
  </Card>
</CardGroup>

# 🔥 Why Activepieces is Different:

* **💖 Loved by Everyone**: Intuitive interface and great experience for both technical and non-technical users with a quick learning curve.

![](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/templates.gif)

* **🌐 Open Ecosystem:** All pieces are open source and available on npmjs.com, **60% of the pieces are contributed by the community**.

* **🛠️  Pieces are written in Typescript**: Pieces are npm packages in TypeScript, offering full customization with the best developer experience, including **hot reloading** for **local** piece development on your machine. 😎

![](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/create-action.png)

* **🤖 AI-Ready**: Native AI pieces let you experiment with various providers, or create your own agents using our AI SDK, and there is Copilot to help you build flows inside the builder.

* **🏢 Enterprise-Ready**: Developers set up the tools, and anyone in the organization can use the no-code builder. Full customization from branding to control.

* **🔒 Secure by Design**: Self-hosted and network-gapped for maximum security and control over your data.

* **🧠 Human in Loop**: Delay execution for a period of time or require approval. These are just pieces built on top of the piece framework, and you can build many pieces like that. 🎨

* **💻 Human Input Interfaces**: Built-in support for human input triggers like "Chat Interface" 💬 and "Form Interface" 📝


# Product Principles
Source: https://www.activepieces.com/docs/getting-started/principles



## 🌟 Keep It Simple

* Design the product to be accessible for everyone, regardless of their background and technical expertise.

* The code is in a monorepository under one service, making it easy to develop, maintain, and scale.

* Keep the technology stack simple to achieve massive adoption.

* Keep the software unopinionated and unlock niche use cases by making it extensible through pieces.

## 🧩 Keep It Extensible

* Automation pieces framework has minimal abstraction and allow you to extend for any usecase.

* All contributions are welcome. The core is open source, and commercial code is available.


# How to handle Requests
Source: https://www.activepieces.com/docs/handbook/customer-support/handle-requests



As a support engineer, you should:

* Fix the urgent issues (please see the definition below)
* Open tickets for all non-urgent issues. **(DO NOT INCLUDE ANY SENSITIVE INFO IN ISSUE)**
* Keep customers updated
* Write clear ticket descriptions
* Help the team prioritize work
* Route issues to the right people

### Ticket fields

When handling support tickets, ensure you set the appropriate status and priority to help with ticket management and response time:

**Status Field**:

These status fields help both our team and customers understand whether an issue will be addressed in future development sprints or requires immediate attention.

* **Backlog**: Issues planned for future development sprints that don't require immediate attention
* **Prioritized**: High-priority issues requiring immediate team focus and resolution

**Priority Levels**:

<Tip>
  Make sure when opening a ticket on Linear to match the priority you have in Pylon. We have a view for immediate tickets (High + Medium priority) to be considered in the next sprint planning.\
  [View Immediate Tickets](https://linear.app/activepieces/team/AP/view/immediate-f6fa2e7fcaed)
</Tip>

During sprint planning, we filter and prioritize customer requests with Medium priority or higher to identify which tickets need immediate attention. This helps us focus our development efforts on the most impactful customer issues.

* **Urgent (P0)**: Emergency issues requiring immediate on-call response
  * Critical system outages
  * Security vulnerabilities
  * Major functionality breakdowns affecting multiple customers

* **High (P1)**: Critical features or blockers
  * Core functionality issues
  * Features essential for customer operations
  * Significant customer-impacting bugs

* **Medium (P2)**: Important but non-critical issues
  * Feature enhancements blocking specific workflows
  * Performance improvements
  * UX improvements affecting usability

* **Low (P3)**: Non-urgent improvements
  * Minor enhancements
  * UI polish
  * Nice-to-have features

### Requests

### Type 1: Quick Fixes & Urgent Issues

* Understand the issue and how urgent it is.
* If the issue is important/urgent and easy to fix, handle it yourself and open a PR right away. This leaves a great impression!

### Type 2: Complex Technical Issues

* Always create a GitHub issue for the feature request, and send it to the customer.
* Assess the issue and determine its urgency.
* Leave a comment on the GitHub issue with an estimated completion time.

### Type 3: Feature Enhancement Requests

* Always create a GitHub issue for the feature request and send it to the customer.
* Evaluate the request and dig deeper into what the customer is trying to solve, then either evaluate and open a new ticket or append to an existing ticket in the backlog.
* Add it to our roadmap and discuss it with the team.

<Tip>
  New features will always have the status "Backlog". Please make sure to communicate that we will discuss and address it in future production cycles so the customer doesn't expect immediate action.
</Tip>

### Frequently Asked Questions

<AccordionGroup>
  <Accordion title="What if I don't understand the feature or issue?">
    If you don't understand the feature or issue, reach out to the customer for clarification. It's important to fully grasp the problem before proceeding. You can also consult with your team for additional insights.
  </Accordion>

  <Accordion title="How do I prioritize multiple urgent issues?">
    When faced with multiple urgent issues, assess the impact of each on the customer and the system. Prioritize based on severity, number of affected users, and potential risks. Communicate with your team to ensure alignment on priorities.
  </Accordion>

  <Accordion title="What if there is an angry or abusive customer?">
    If you encounter an abusive or rude customer, escalate the issue to Mohammad AbuAboud or Ashraf Samhouri. It's important to handle such situations with care and ensure that the customer feels heard while maintaining a respectful and professional demeanor.
  </Accordion>
</AccordionGroup>


# Overview
Source: https://www.activepieces.com/docs/handbook/customer-support/overview



At Activepieces, we take a unique approach to customer support. Instead of having dedicated support staff, our full-time engineers handle support requests on rotation. This ensures you get expert technical help from the people who build the product.

### Support Schedule

Our on-call engineer handles customer support as part of their rotation. For more details about how this works, check out our on-call documentation.

### Support Channels

* Community Support
  * GitHub Issues: We actively monitor and respond to issues on our [GitHub repository](https://github.com/activepieces/activepieces)
  * Community Forum: We engage with users on our [Community Platform](https://community.activepieces.com/) to provide help and gather feedback
  * Email: only for account related issues, delete account request or billing issues.

* Enterprise Support
  * Enterprise customers receive dedicated support through Slack
  * We use [Pylon](https://usepylon.com) to manage support tickets and customer channels efficiently
  * For detailed information on using Pylon, see our [Pylon Guide](handbook/customer-support/pylon)

### Support Hours & SLA:

<Warning>
  Work in progress—coming soon!
</Warning>


# How to use Pylon
Source: https://www.activepieces.com/docs/handbook/customer-support/pylon

Guide for using Pylon to manage customer support tickets

At Activepieces, we use Pylon to manage Slack-based customer support requests through a Kanban board.

Learn more about Pylon's features: [https://docs.usepylon.com/pylon-docs](https://docs.usepylon.com/pylon-docs)

![Pylon board showing different columns for ticket management](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/pylon-board.png)

### New Column

Contains new support requests that haven't been reviewed yet

* Action Items:
  * Respond fast even if you don't have an answer, the important thing here is to reply that you will take a look into it, the key to winning the customer's heart.

### On You Column

Contains active tickets that require your attention and response. These tickets need immediate review and action.

* Action items:
  * Set ticket fields (status and priority) according to the guide below
  * Check the [handle request page](./handle-requests) on how to handle tickets

<Tip>
  The goal as a support engineer is to keep the "New" and "On You" columns empty.
</Tip>

### On Hold

Contains only tickets that have a linked Linear issue.

* Place tickets here after:
  * You have identified the customer's issue
  * You have created a Linear issue (if one doesn't exist - avoid duplicates!)
  * You have linked the issue in Pylon
  * You have assigned it to a team member (for urgent cases only)

<Warning>
  Please do not place tickets on hold without a ticket.
</Warning>

<Note>
  Tickets will automatically move back to the "On You" column when the linked GitHub issue is closed.
</Note>

### Closed Column

This means you did awesome job and the ticket reached it's Final destination for resolved tickets and no further attention required.


# Tone & Communication
Source: https://www.activepieces.com/docs/handbook/customer-support/tone



Our customers are fellow engineers and great people to work with. This guide will help you understand the tone and communication style that reflects Activepieces' culture in customer support.

#### Casual

Chat with them like you're talking to a friend. There's no need to sound like a robot. For example:

* ✅ "Hey there! How can I help you today?"
* ❌ "Greetings. How may I assist you with your inquiry?"
* ✅ "No worries, we'll get this sorted out together!"
* ❌ "Please hold while I process your request."

#### Fast

Reply quickly! People love fast responses. Even if you don't know the answer right away, let them know you'll get back to them with the information. This is the fastest way to make customers happy; everyone likes to be heard.

#### Honest

Explain the issue clearly, don't be defensive, and be honest. We're all about open source and transparency here – it's part of our culture. For example:

* ✅ "I'm sorry, I forgot to follow up on this. Let's get it sorted out now."
* ❌ "I apologize for the delay; there were unforeseen circumstances."

### Always Communicate the Next Step

Always clarify the next step, such as whether the ticket will receive an immediate response or be added to the backlog for team discussion.

#### Use "we," not "I"

* ✅ "We made a mistake here. We'll fix that for you."
* ❌ "I'll look into this for you."
* You're speaking on behalf of the company in every email you send.
* Use "we" to show customers they have the whole team's support.

<Tip>
  Customers are real people who want to talk to real people. Be yourself, be helpful, and focus on solving their problems!
</Tip>


# Trial Key Management
Source: https://www.activepieces.com/docs/handbook/customer-support/trial

Description of your new file.

Please read more how to create development / production keys for the customer in the following document.

* [Trial Key Management Guide](https://docs.google.com/document/d/1k4-_ZCgyejS9UKA7AwkSB-l2TEZcnK2454o2joIgm4k/edit?tab=t.0#heading=h.ziaohggn8z8d): Includes detailed instructions on generating and extending 14-day trial keys.


# Handling Downtime
Source: https://www.activepieces.com/docs/handbook/engineering/onboarding/downtime-incident



![Downtime Incident](https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExdTZnbGxjc3k5d3NxeXQwcmhxeTRsbnNybnd4NG41ZnkwaDdsa3MzeSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/2UCt7zbmsLoCXybx6t/giphy.gif)

## 📋 What You Need Before Starting

Make sure these are ready:

* **[Incident.io Setup](../playbooks/setup-incident-io)**: For managing incidents.
* **Grafana & Loki**: For checking logs and errors.
* **Checkly Debugging**: For testing and monitoring.

***

## 🚨 Stay Calm and Take Action

<Warning>
  Don’t panic! Follow these steps to fix the issue.
</Warning>

1. **Tell Your Users**:
   * Let your users know there’s an issue. Post on [Community](https://community.activepieces.com) and Discord.
   * Example message: *“We’re looking into a problem with our services. Thanks for your patience!”*

2. **Find Out What’s Wrong**:
   * Gather details. What’s not working? When did it start?

3. **Update the Status Page**:
   * Use [Incident.io](https://incident.io) to update the status page. Set it to *“Investigating”* or *“Partial Outage”*.

***

## 🔍 Check for Infrastructure Problems

1. **Look at DigitalOcean**:
   * Check if the CPU, memory, or disk usage is too high.
   * If it is:
     * **Increase the machine size** temporarily to fix the issue.
     * Keep looking for the root cause.

***

## 📜 Check Logs and Errors

1. **Use Grafana & Loki**:
   * Search for recent errors in the logs.
   * Look for anything unusual or repeating.

2. **Check Sentry**:
   * Look for grouped errors (errors that happen a lot).
   * Try to **reproduce the error** and fix it if possible.

***

## 🛠️ Debugging with Checkly

1. **Check Checkly Logs**:
   * Watch the **video recordings** of failed checks to see what went wrong.
   * If the issue is a **timeout**, it might mean there’s a bigger performance problem.
   * If it's an E2E test failure due to UI changes, it's likely not urgent.
     * Fix the test and the issue will go away.

***

## 🚨 When Should You Ask for Help?

Ask for help right away if:

* Flows are failing.
* The whole platform is down.
* There's a lot of data loss or corruption.
* You're not sure what is causing the issue.
* You've spent **more than 5 minutes** and still don't know what's wrong.

💡 **How to Ask for Help**:

* Use **Incident.io** to create a **critical alert**.
* Go to the **Slack incident channel** and escalate the issue to the engineering team.

<Warning>
  If you’re unsure, **ask for help!** It’s better to be safe than sorry.
</Warning>

***

## 💡 Helpful Tips

1. **Stay Organized**:
   * Keep a list of steps to follow during downtime.
   * Write down everything you do so you can refer to it later.

2. **Communicate Clearly**:
   * Keep your team and users updated.
   * Use simple language in your updates.

3. **Take Care of Yourself**:
   * If you feel stressed, take a short break. Grab a coffee ☕, take a deep breath, and tackle the problem step by step.


# Engineering Workflow
Source: https://www.activepieces.com/docs/handbook/engineering/onboarding/how-we-work



Activepieces work is based on one-week sprints, as priorities change fast, the sprint has to be short to adapt.

## Sprints

Sprints are shared publicly on our GitHub account. This would give everyone visibility into what we are working on.

* There should be a GitHub issue for the sprint set up in advance that outlines the changes.
* Each *individual* should come prepared with specific suggestions for what they will work on over the next sprint. **if you're in an engineering role, no one will dictate to you what to build – it is up to you to drive this.**
* Teams generally meet once a week to pick the **priorities** together.
* Everyone in the team should attend the sprint planning.
* Anyone can comment on the sprint issue before or after the sprint.

## Pull Requests

When it comes to code review, we have a few guidelines to ensure efficiency:

* Create a pull request in draft state as soon as possible.
* Be proactive and review other people’s pull requests. Don’t wait for someone to ask for your review; it’s your responsibility.
* Assign only one reviewer to your pull request.
* **It is the responsibility of the PR owner to draft the test scenarios within the PR description. Upon review, the reviewer may assume that these scenarios have been tested and provide additional suggestions for scenarios.**
* **Large, incomplete features should be broken down into smaller tasks and continuously merged into the main branch.**

## Planning is everyone's job.

Every engineer is responsible for discovering bugs/opportunities and bringing them up in the sprint to convert them into actionable tasks.


# On-Call
Source: https://www.activepieces.com/docs/handbook/engineering/onboarding/on-call



## Prerequisites:

* [Setup Incident IO](../playbooks/setup-incident-io)

## Why On-Call?

We need to ensure there is **exactly one person** at the same time who is the main point of contact for the users and the **first responder** for the issues. It's also a great way to learn about the product and the users and have some fun.

<Tip>
  You can listen to [Queen - Under Pressure](https://www.youtube.com/watch?v=a01QQZyl-_I) while on-call, it's fun and motivating.
</Tip>

<Tip>
  If you ever feel burn out in middle of your rotation, please reach out to the team and we will help you with the rotation or take over the responsibility.
</Tip>

## On-Call Schedule

The on-call rotation is managed through Incident.io, with each engineer taking a one-week shift. You can:

* View the current schedule and upcoming rotations on [Incident.io On-Call Schedule](https://app.incident.io/activepieces/on-call/schedules)
* Add the schedule to your Google Calendar using [this link](https://calendar.google.com/calendar/r?cid=webcal://app.incident.io/api/schedule_feeds/cc024d13704b618cbec9e2c4b2415666dfc8b1efdc190659ebc5886dfe2a1e4b)

<Warning>
  Make sure to update the on-call schedule in Incident.io if you cannot be available during your assigned rotation. This ensures alerts are routed to the correct person and maintains our incident response coverage.

  To modify the schedule:

  1. Go to [Incident.io On-Call Schedule](https://app.incident.io/activepieces/on-call/schedules)
  2. Find your rotation slot
  3. Click "Override schedule" to mark your unavailability
  4. Coordinate with the team to find coverage for your slot
</Warning>

## What it means to be on-call

The primary objective of being on-call is to triage issues and assist users. It is not about fixing the issues or coding missing features. Delegation is key whenever possible.

You are responsible for the following:

* Respond to Slack messages as soon as possible, referring to the [customer support guidelines](./customer-support.mdx).

* Check [community.activepieces.com](https://community.activepieces.com) for any new issues or to learn about existing issues.

* Monitor your Incident.io notifications and respond promptly when paged.

<Tip>
  **Friendly Tip #1**: always escalate to the team if you are unsure what to do.
</Tip>

## How do you get paged?

Monitor and respond to incidents that come through these channels:

#### Slack Fire Emoji (🔥)

When a customer reports an issue in Slack and someone reacts with 🔥, you'll be automatically paged and a dedicated incident channel will be created.

#### Automated Alerts

Watch for notifications from:

* Digital Ocean about CPU, Memory, or Disk outages
* Checkly about e2e test failures or website downtime


# Overview
Source: https://www.activepieces.com/docs/handbook/engineering/overview



Welcome to the engineering team! This section contains essential information to help you get started, including our development processes, guidelines, and practices. We're excited to have you on board.


# Queues Dashboard
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/bullboard



The Bull Board is a tool that allows you to check issues with scheduling and internal flow runs issues.

![BullBoard Overview](https://raw.githubusercontent.com/felixmosh/bull-board/master/screenshots/overview.png)

## Setup BullBoard

To enable the Bull Board UI in your self-hosted installation:

1. Define these environment variables:
   * `AP_QUEUE_UI_ENABLED`: Set to `true`
   * `AP_QUEUE_UI_USERNAME`: Set your desired username
   * `AP_QUEUE_UI_PASSWORD`: Set your desired password

2. Access the UI at `/api/ui`

<Tip>
  For cloud installations, please ask your team for access to the internal documentation that explains how to access BullBoard.
</Tip>

## Common Issues

### Scheduling Issues

If a scheduled flow is not triggering as expected:

1. Check the `repeatableJobs` queue in BullBoard to verify the job exists
2. Verify the job status is not "failed" or "delayed"
3. Check that the cron expression or interval is configured correctly
4. Look for any error messages in the job details

### Flow Stuck in "Running" State

If a flow appears stuck in the running state:

1. Check the `oneTimeJobs` queue for the corresponding job
2. Look for:
   * Jobs in "delayed" state (indicates retry attempts)
   * Jobs in "failed" state (indicates execution errors)
3. Review the job logs for error messages or timeouts
4. If needed, you can manually remove stuck jobs through the BullBoard UI

## Queue Overview

We maintain four main queues in our system:

#### Scheduled Queue (`repeatableJobs`)

Contains both polling and delayed jobs.

<Info>
  Failed jobs are not normal and need to be checked right away to find and fix what's causing them.
</Info>

<Tip>
  Delayed jobs represent either paused flows scheduled for future execution or upcoming polling job iterations.
</Tip>

#### One-Time Queue (`oneTimeJobs`)

Handles immediate flow executions that run only once

<Info>
  * Delayed jobs indicate an internal system error occurred and the job will be retried automatically according to the backoff policy
  * Failed jobs require immediate investigation as they represent executions that failed for unknown reasons that could indicate system issues
</Info>

#### Webhook Queue (`webhookJobs`)

Handles incoming webhook triggers

<Info>
  * Delayed jobs indicate an internal system error occurred and the job will be retried automatically according to the backoff policy
  * Failed jobs require immediate investigation as they represent executions that failed for unknown reasons that could indicate system issues
</Info>

#### Users Interaction Queue (`usersInteractionJobs`)

Handles operations that are directly initiated by users, including:
• Installing pieces
• Testing flows
• Loading dropdown options
• Executing triggers
• Executing actions

<Info>
  Failed jobs in this queue are not retried since they represent real-time user actions that should either succeed or fail immediately
</Info>


# Database Migrations
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/database-migration

Guide for creating database migrations in Activepieces

Activepieces uses TypeORM as its database driver in Node.js. We support two database types across different editions of our platform.

The database migration files contain both what to do to migrate (up method) and what to do when rolling back (down method).

<Tip>
  Read more about TypeORM migrations here:
  [https://orkhan.gitbook.io/typeorm/docs/migrations](https://orkhan.gitbook.io/typeorm/docs/migrations)
</Tip>

## Database Support

* PostgreSQL
* SQLite

<Tip>
  **Why Do we have SQLite?**
  We support SQLite to simplify development and self-hosting. It's particularly helpful for:

  * Developers creating pieces who want a quick setup
  * Self-hosters using platforms to manage docker images but doesn't support docker compose.
</Tip>

## Editions

* **Enterprise & Cloud Edition** (Must use PostgreSQL)
* **Community Edition** (Can use PostgreSQL or SQLite)

<Tip>
  If you are generating a migration for an entity that will only be used in Cloud & Enterprise editions, you only need to create the PostgreSQL migration file. You can skip generating the SQLite migration.
</Tip>

### How To Generate

<Steps>
  <Step title="Uncomment Database Connection Export">
    Uncomment the following line in `packages/server/api/src/app/database/database-connection.ts`:

    ```typescript
    export const exportedConnection = databaseConnection()
    ```
  </Step>

  <Step title="Configure Database Type">
    Edit your `.env` file to set the database type:

    ```env
    # For SQLite migrations (default)
    AP_DATABASE_TYPE=SQLITE
    ```

    For PostgreSQL migrations:

    ```env
    AP_DATABASE_TYPE=POSTGRES
    AP_POSTGRES_DATABASE=activepieces
    AP_POSTGRES_HOST=db
    AP_POSTGRES_PORT=5432
    AP_POSTGRES_USERNAME=postgres
    AP_POSTGRES_PASSWORD=password
    ```
  </Step>

  <Step title="Generate Migration">
    Run the migration generation command:

    ```bash
    nx db-migration server-api name=<MIGRATION_NAME>
    ```

    Replace `<MIGRATION_NAME>` with a descriptive name for your migration.
  </Step>

  <Step title="Move Migration File">
    The command will generate a new migration file in `packages/server/api/src/app/database/migrations`.
    Review the generated file and:

    * For PostgreSQL migrations: Move it to `postgres-connection.ts`
    * For SQLite migrations: Move it to `sqlite-connection.ts`
  </Step>

  <Step title="Re-comment Export">
    After moving the file, remember to re-comment the line from step 1:

    ```typescript
    // export const exportedConnection = databaseConnection()
    ```
  </Step>
</Steps>

<Tip>
  Always test your migrations by running them both up and down to ensure they work as expected.
</Tip>


# Cloud Infrastructure
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/infrastructure



<Warning>
  The playbooks are private, Please ask your team for an access.
</Warning>

Our infrastructure stack consists of several key components that help us monitor, deploy, and manage our services effectively.

## Hosting Providers

We use two main hosting providers:

* **DigitalOcean**: Hosts our databases including Redis and PostgreSQL
* **Hetzner**: Provides the machines that run our services

## Grafana (Loki) for Logs

We use Grafana Loki to collect and search through logs from all our services in one centralized place.

## Kamal for Deployment

Kamal is a deployment tool that helps us deploy our Docker containers to production with zero downtime.


# Feature Announcement
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/product-announcement



When we develop new features, our marketing team handles the public announcements. As engineers, we need to clearly communicate:

1. The problem the feature solves
2. The benefit to our users
3. How it integrates with our product

### Handoff to Marketing Team

After releasing a feature, create a ticket for the marketing team in Linear: [https://linear.app/activepieces/team/MAR/active](https://linear.app/activepieces/team/MAR/active).

<Tip>
  Please include a video showing the marketing team  on how to use this feature so they can create a demo video and market it correctly.
</Tip>

Ticket templates:

```
### What Problem Does This Feature Solve?

### Explain How the Feature Works
[Insert the video link here]

### Relevant User Scenarios
[Insert Pylon tickets or community posts here]
```


# How to create Release
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/releases



Pre-releases are versions of the software that are released before the final version. They are used to test new features and bug fixes before they are released to the public. Pre-releases are typically labeled with a version number that includes a pre-release identifier, such as `official` or `rc`.

## Types of Releases

There are several types of releases that can be used to indicate the stability of the software:

* **Official**: Official releases are considered to be stable and are close to the final release.
* **Release Candidate (RC)**: Release candidates are versions of the software that are feature-complete and have been tested by a larger group of users. They are considered to be stable and are close to the final release. They are typically used for final testing before the final release.

## Why Use Pre-Releases

We do pre-release when we release hot-fixes / bug fixes / small and beta features.

## How to Release a Pre-Release

To release a pre-release version of the software, follow these steps:

1. **Create a new branch**: Create a new branch from the `main` branch. The branch name should be `release/vX.Y.Z` where `X.Y.Z` is the version number.
2. **Increase the version number**: Update the `package.json` file with the new version number.
3. **Open a Pull Request**: Open a pull request from the new branch to the `main` branch. Assign the `pre-release` label to the pull request.
4. **Check the Changelog**: Check the [Activepieces Releases](https://github.com/activepieces/activepieces/releases) page to see if there are any new features or bug fixes that need to be included in the pre-release. Make sure all PRs are labeled correctly so they show in the correct auto-generated changelog. If not, assign the labels and rerun the changelog by removing the "pre-release" label and adding it again to the PR.
5. Go to [https://github.com/activepieces/activepieces/actions/workflows/release-rc.yml](https://github.com/activepieces/activepieces/actions/workflows/release-rc.yml) and run it on the release branch to build the rc image.
6. **Merge the Pull Request**: Merge the pull request to the `main` branch.
7. **Release the Notes**: Release the notes for the new version.


# Setup Incident.io
Source: https://www.activepieces.com/docs/handbook/engineering/playbooks/setup-incident-io



Incident.io is our primary tool for managing and responding to urgent issues and service disruptions.
This guide explains how we use Incident.io to coordinate our on-call rotations and emergency response procedures.

## Setup and Notifications

### Personal Setup

1. Download the Incident.io mobile app from your device's app store
2. Ask your team to add you to the Incident.io workspace
3. Configure your notification preferences:
   * Phone calls for critical incidents
   * Push notifications for high-priority issues
   * Slack notifications for standard updates

### On-Call Rotations

Our team operates on a weekly rotation schedule through Incident.io, where every team member participates. When you're on-call:

* You'll receive priority notifications for all urgent issues
* Phone calls will be placed for critical service disruptions
* Rotations change every week, with handoffs occurring on Monday mornings
* Response is expected within 15 minutes for critical incidents

<Tip>
  If you are unable to respond to an incident, please escalate to the engineering team.
</Tip>


# Our Compensation
Source: https://www.activepieces.com/docs/handbook/hiring/compensation



The packages include three factors for the salary:

* **Role**: The specific position and responsibilities of the employee.
* **Location**: The geographical area where the employee is based.
* **Level**: The seniority and experience level of the employee.

<Tip>Salaries are fixed and based on levels and seniority, not negotiation. This ensures fair pay for everyone.</Tip>

<Tip>Salaries are updated based on market trends and the company's performance. It's easier to justify raises when the business is great.</Tip>


# Our Hiring Process
Source: https://www.activepieces.com/docs/handbook/hiring/hiring



Engineers are the majority of the Activepieces team, and we are always looking for highly talented product engineers.

<Steps>
  <Step title="Technical Interview">
    Here, you'll face a real challenge from Activepieces. We'll guide you through it to see how you solve problems.
  </Step>

  <Step title="Product & Leadership Interview">
    We'll chat about your past experiences and how you design products. It's like having a friendly conversation where we reflect on what you've done before.
  </Step>

  <Step title="Work Trial">
    You'll do open source task for one day. This open source contribution task help us understand how well we work together.
  </Step>
</Steps>

## Interviewing Tips

Every interview should make us say **HELL YES**. If not, we'll kindly pass.

**Avoid Bias:** Get opinions from others to make fair decisions.

**Speak Up Early:** If you're unsure about something, ask or test it right away.


# Our Roles & Levels
Source: https://www.activepieces.com/docs/handbook/hiring/levels



**Product Engineers** are full stack engineers who handle both the engineering and product side, delivering features end-to-end.

### Our Levels

We break out seniority into three levels, **L1 to L3**.

### L1 Product Engineers

They tend to be early-career.

* They get more management support than folks at other levels.
* They focus on continuously absorbing new information about our users and how to be effective at **Activepieces**.
* They aim to be increasingly autonomous as they gain more experience here.

### L2 Product Engineers

They are generally responsible for running a project start-to-finish.

* They independently decide on the implementation details.
* They work with **Stakeholders** / **teammates** / **L3s** on the plan.
* They have personal responsibility for the **“how”** of what they’re working on, but share responsibility for the **“what”** and **“why”**.
* They make consistent progress on their work by continuously defining the scope, incorporating feedback, trying different approaches and solutions, and deciding what will deliver the most value for users.

### L3 Product Engineers

Their scope is bigger than coding, they lead a product area, make key product decisions and guide the team with strong leadership skills.

* **Planning**: They help **L2s** figure out what the next priority things to focus on and guide **L1s** in determining the right sequence of work to get a project done.
* **Day-to-Day Work**: They might be hands-on with the day-to-day work of the team, providing support and resources to their teammates as needed.
* **Customer Communication**: They handle direct communication with customers regarding planning and product direction, ensuring that customer needs and feedback are incorporated into the development process.

### How to Level Up

There is no formal process, but it happens at the end of **each year** and is based on two things:

1. **Manager Review**: Managers look at how well the engineer has performed and grown over the year.
2. **Peer Review**: Colleagues give feedback on how well the engineer has worked with the team.

This helps make sure promotions are fair and based on merit.


# Our Team Structure
Source: https://www.activepieces.com/docs/handbook/hiring/team



We are big believers in small teams with 10x engineers who would outperform other team types.

## No product management by default

Engineers decide what to build. If you need help, feel free to reach out to the team for other opinions or help.

## No Process by default

We trust the engineers' judgment to make the call whether this code is risky and requires external approval or if it's a fix that can be easily reversed or fixed with no big impact on the end user.

## They Love Users

When the engineer loves the users, that means they would ship fast, they wouldn't over-engineer because they understand the requirements very well, they usually have empathy which means they don't complicate everyone else.

## Pragmatic & Speed

Engineering planning sometimes seems sexy from a technical perspective, but being pragmatic means you would take decisions in a timely manner, taking them in baby steps and iterating faster rather than planning for the long run, and it's easy to reverse wrong decisions early on without investing too much time.

## Starts With Hiring

We hire very **slowly**. We are always looking for highly talented engineers. We love to hire people with a broader skill set and flexibility, low egos, and who are builders at heart.

We found that working with strong engineers is one of the strongest reasons to retain employees, and this would allow everyone to be free and have less process.


# Activepieces Handbook
Source: https://www.activepieces.com/docs/handbook/overview



Welcome to the Activepieces Handbook!

This guide serves as a complete resource for understanding our organization. Inside, you'll find detailed sections covering various aspects of our internal processes and policies.


# AI Agent
Source: https://www.activepieces.com/docs/handbook/teams/ai



### Mission Statement

We use AI to help you build workflows quickly and easily, turning your ideas into working automations in minutes.

### People

<CardGroup col={3}>
  <Snippet file="profile/amr.mdx" />

  <Snippet file="profile/mo.mdx" />

  <Snippet file="profile/ash.mdx" />

  <Snippet file="profile/issa.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/copilot-1f9e2549f61c/issues](https://linear.app/activepieces/project/copilot-1f9e2549f61c/issues)


# Marketing & Content
Source: https://www.activepieces.com/docs/handbook/teams/content



### Mission Statement

We aim to share and teach Activepieces' vision of democratized automation, helping users discover and learn how to unlock the full potential of our platform while building a vibrant community of automation enthusiasts.

### People

<CardGroup col={3}>
  <Snippet file="profile/ash.mdx" />

  <Snippet file="profile/kareem.mdx" />

  <Snippet file="profile/ginika.mdx" />

  <Snippet file="profile/sanad.mdx" />
</CardGroup>


# Developer Experience & Infrastructure
Source: https://www.activepieces.com/docs/handbook/teams/developer-experience



### Mission Statement

We build and maintain developer tools, infrastructure, and documentation to improve the productivity and satisfaction of developers working with our platform. We also ensure Activepieces is easy to self-host by providing clear documentation, deployment guides, and infrastructure tooling.

### People

<CardGroup col={3}>
  <Snippet file="profile/hazem.mdx" />

  <Snippet file="profile/khaled.mdx" />

  <Snippet file="profile/mo.mdx" />

  <Snippet file="profile/kishan.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/self-hosting-devxp-infrastructure-cc6611474f1f/overview](https://linear.app/activepieces/project/self-hosting-devxp-infrastructure-cc6611474f1f/overview)


# Embedding
Source: https://www.activepieces.com/docs/handbook/teams/embed-sdk



### Mission Statement

We build a robust SDK that makes it simple for developers to embed Activepieces automation capabilities into any application.

### People

<CardGroup col={3}>
  <Snippet file="profile/abdulyki.mdx" />

  <Snippet file="profile/mo.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/embedding-085e6ea3fef0/overview](https://linear.app/activepieces/project/embedding-085e6ea3fef0/overview)


# Flow Editor & Dashboard
Source: https://www.activepieces.com/docs/handbook/teams/flow-builder



### Mission Statement

We aim to build a simple yet powerful tool that helps people automate tasks without coding. Our goal is to make it easy for anyone to use. We build and maintain the flow editor that enables users to create and manage automated workflows through an intuitive interface.

### People

<CardGroup col={3}>
  <Snippet file="profile/abdulyki.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/flow-editor-and-execution-bd53ec32d508/overview](https://linear.app/activepieces/project/flow-editor-and-execution-bd53ec32d508/overview)


# Human in the Loop
Source: https://www.activepieces.com/docs/handbook/teams/human-in-loop



### Mission Statement

We build and maintain features that enable human interaction within automated workflows, including forms, approvals, and chat interfaces.

### People

<CardGroup col={3}>
  <Snippet file="profile/hazem.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/human-in-the-loop-8eb571776a92/overview](https://linear.app/activepieces/project/human-in-the-loop-8eb571776a92/overview)


# Dashboard & Platform Admin
Source: https://www.activepieces.com/docs/handbook/teams/management-features



### Mission Statement

We build and maintain the platform administration capabilities and dashboard features, ensuring secure and efficient management of users, organizations, and system resources.

### People

<CardGroup col={3}>
  <Snippet file="profile/abdulyki.mdx" />

  <Snippet file="profile/hazem.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/management-features-0e61486373e7/overview](https://linear.app/activepieces/project/management-features-0e61486373e7/overview)


# Overview
Source: https://www.activepieces.com/docs/handbook/teams/overview



<CardGroup cols={2}>
  <Card title="AI" icon="robot" href="/handbook/teams/ai" color="#8E44AD">
    Leverage artificial intelligence capabilities across the platform
  </Card>

  <Card title="Business Operations" icon="briefcase" href="/handbook/teams/business-operations" color="#96CEB4">
    Manage day-to-day business operations and workflows
  </Card>

  <Card title="Developer Experience" icon="code-branch" href="/handbook/teams/developer-experience" color="#34495E">
    Build tools and infrastructure to improve developer productivity and satisfaction
  </Card>

  <Card title="Embedding" icon="code" href="/handbook/teams/embed-sdk" color="#9B59B6">
    Integrate and embed platform functionality into your applications
  </Card>

  <Card title="Flow Execution & Editor" icon="gears" href="/handbook/teams/flow-builder" color="#2ECC71">
    Run and monitor automated workflows with high performance and reliability
  </Card>

  <Card title="Human in the Loop" icon="user-check" href="/handbook/teams/human-in-the-loop" color="#E67E22">
    Design and implement human review and approval processes
  </Card>

  <Card title="Management Features" icon="shield" href="/handbook/teams/management-features" color="#E74C3C">
    Build and maintain platform administration capabilities and dashboard features
  </Card>

  <Card title="Marketing Website & Content" icon="pencil" href="/handbook/teams/content" color="#FF6B6B">
    Create and manage educational content, documentation, and marketing copy
  </Card>

  <Card title="Pieces" icon="puzzle-piece" href="/handbook/teams/pieces" color="#F1C40F">
    Build and manage integration pieces to connect with external services
  </Card>

  <Card title="Platform" icon="shield-halved" href="/handbook/teams/platform-admin" color="#45B7D1">
    Manage platform infrastructure, security, and core services
  </Card>

  <Card title="Sales" icon="handshake" href="/handbook/teams/sales" color="#27AE60">
    Grow revenue by selling Activepieces to businesses
  </Card>

  <Card title="Tables" icon="table" href="/handbook/teams/tables" color="#3498DB">
    Create and manage data tables
  </Card>
</CardGroup>

### People

<CardGroup col={3}>
  <Snippet file="profile/ash.mdx" />

  <Snippet file="profile/mo.mdx" />

  <Snippet file="profile/abdulyki.mdx" />

  <Snippet file="profile/abood.mdx" />

  <Snippet file="profile/kishan.mdx" />

  <Snippet file="profile/hazem.mdx" />

  <Snippet file="profile/ginika.mdx" />

  <Snippet file="profile/kareem.mdx" />

  <Snippet file="profile/amr.mdx" />

  <Snippet file="profile/sanad.mdx" />

  <Snippet file="profile/aboodzein.mdx" />

  <Snippet file="profile/issa.mdx" />
</CardGroup>


# Pieces
Source: https://www.activepieces.com/docs/handbook/teams/pieces



### Mission Statement

We build and maintain integration pieces that enable users to connect and automate across different services and platforms.

### People

<CardGroup col={3}>
  <Snippet file="profile/kishan.mdx" />

  <Snippet file="profile/abood.mdx" />
</CardGroup>

### Roadmap

#### Third Party Pieces

[https://linear.app/activepieces/project/third-party-pieces-38b9d73a164c/issues](https://linear.app/activepieces/project/third-party-pieces-38b9d73a164c/issues)

#### Core Pieces

[https://linear.app/activepieces/project/core-pieces-3419406029ca/issues](https://linear.app/activepieces/project/core-pieces-3419406029ca/issues)

#### Universal AI Pieces

[https://linear.app/activepieces/project/universal-ai-pieces-92ed6f9cd12b/issues](https://linear.app/activepieces/project/universal-ai-pieces-92ed6f9cd12b/issues)


# Sales
Source: https://www.activepieces.com/docs/handbook/teams/sales



### Mission Statement

We grow revenue by selling Activepieces to businesses.

### People

<CardGroup col={3}>
  <Snippet file="profile/ash.mdx" />
</CardGroup>


# Tables
Source: https://www.activepieces.com/docs/handbook/teams/tables



### Mission Statement

We build powerful yet simple data table capabilities that allow users to store, manage and manipulate their data within their automation workflows.

### People

<CardGroup col={3}>
  <Snippet file="profile/amr.mdx" />
</CardGroup>

### Roadmap

[https://linear.app/activepieces/project/data-tables-files-81237f412ac5/issues](https://linear.app/activepieces/project/data-tables-files-81237f412ac5/issues)


# Engine
Source: https://www.activepieces.com/docs/install/architecture/engine



The Engine file contains the following types of operations:

* **Extract Piece Metadata**: Extracts metadata when installing new pieces.
* **Execute Step**: Executes a single test step.
* **Execute Flow**: Executes a flow.
* **Execute Property**: Executes dynamic dropdowns or dynamic properties.
* **Execute Trigger Hook**: Executes actions such as OnEnable, OnDisable, or extracting payloads.
* **Execute Auth Validation**: Validates the authentication of the connection.

The engine takes the flow JSON with an engine token scoped to this project and implements the API provided for the piece framework, such as:

* Storage Service: A simple key/value persistent store for the piece framework.
* File Service: A helper to store files either locally or in a database, such as for testing steps.
* Fetch Metadata: Retrieves metadata of the current running project.


# Overview
Source: https://www.activepieces.com/docs/install/architecture/overview



This page focuses on describing the main components of Activepieces and focus mainly on workflow executions.

## Components

![Architecture](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/architecture.png)

**Activepieces:**

* **App**: The main application that organizes everything from APIs to scheduled jobs.
* **Worker**: Polls for new jobs and executes the flows with the engine, ensuring proper sandboxing, and sends results back to the app through the API.
* **Engine**: TypeScript code that parses flow JSON and executes it. It is compiled into a single JS file.
* **UI**: Frontend written in React.

**Third Party**:

* **Postgres**: The main database for Activepieces.
* **Redis**: This is used to power the queue using [BullMQ](https://docs.bullmq.io/).

## Reliability & Scalability

<Tip>
  Postgres and Redis availability is outside the scope of this documentation, as many cloud providers already implement best practices to ensure their availability.
</Tip>

* **Webhooks**:\
  All webhooks are sent to the Activepieces app, which performs basic validation and adds them to the queue. In case of a spike, webhooks will be added to the queue.

* **Polling Trigger**:\
  All recurring jobs are added to Redis. In case of a failure, the missed jobs will be executed again.

* **Flow Execution**:\
  Workers poll jobs from the queue. In the event of a spike, the flow execution will still work but may be delayed depending on the size of the spike.

To scale Activepieces, you typically need to increase the replicas of either workers, the app, or the Postgres database. A small Redis instance is sufficient as it can handle thousands of jobs per second and rarely acts as a bottleneck.

## Repository Structure

The repository is structured as a monorepo using the NX build system, with TypeScript as the primary language. It is divided into several packages:

```
.
├── packages
│   ├── react-ui
│   ├── server
|       |── api
|       |── worker
|       |── shared
|   ├── ee
│   ├── engine
│   ├── pieces
│   ├── shared
```

* `react-ui`: This package contains the user interface, implemented using the React framework.
* `server-api`: This package contains the main application written in TypeScript with the Fastify framework.
* `server-worker`: This package contains the logic of accepting flow jobs and executing them using the engine.
* `server-shared`: this package contains the shared logic between worker and app.
* `engine`: This package contains the logic for flow execution within the sandbox.
* `pieces`: This package contains the implementation of triggers and actions for third-party apps.
* `shared`: This package contains shared data models and helper functions used by the other packages.
* `ee`: This package contains features that are only available in the paid edition.


# Stack & Tools
Source: https://www.activepieces.com/docs/install/architecture/stack



## Language

Activepieces uses **Typescript** as its one and only language.
The reason behind unifying the language is the ability for it to break data models and features into packages, which can be shared across its components (worker / frontend / backend).

This enables it to focus on learning fewer tooling options and perfect them across all its packages.

## Frontend

* Web framework/library: [React](https://reactjs.org/)
* Layout/components: [shadcn](https://shadcn.com/) / Tailwind

## Backend

* Framework: [Fastify](https://www.fastify.io/)
* Database: [PostgreSQL](https://www.postgresql.org/)
* Task Queuing: [Redis](https://redis.io/)
* Task Worker: [BullMQ](https://github.com/taskforcesh/bullmq)

## Testing

* Unit & Integration Tests: [Jest](https://jestjs.io/)
* E2E Test: [Playwright](https://playwright.dev/)

## Additional Tools

* Application monitoring: [Sentry](https://sentry.io/welcome/)
* CI/CD: [GitHub Actions](https://github.com/features/actions) / [Depot](https://depot.dev/) / [Kamal](https://kamal-deploy.org/)
* Containerization: [Docker](https://www.docker.com/)
* Linter: [ESLint](https://eslint.org/)
* Logging: [Loki](https://grafana.com/)
* Building: [NX Monorepo](https://nx.dev/)

## Adding New Tool

Adding a new tool isn't a simple choice. A simple choice is one that's easy to do or undo, or one that only affects your work and not others'.

We avoid adding new stuff to increase the ease of setup, which increases adoption. Having more dependencies means more moving parts and support.

If you're thinking about a new tool, ask yourself these:

* Is this tool open source? How can we give it to customers who use their own servers?
* What does it fix, and why do we need it now?
* Can we use what we already have instead?

These questions only apply to required services for everyone. If this tool speeds up your own work, we don't need to think so hard.


# Workers & Sandboxing
Source: https://www.activepieces.com/docs/install/architecture/workers



This component is responsible for polling jobs from the app, preparing the sandbox, and executing them with the engine.

## Jobs

There are three types of jobs:

* **Recurring Jobs**: Polling/schedule triggers jobs for active flows.
* **Flow Jobs**: Flows that are currently being executed.
* **Webhook Jobs**: Webhooks that still need to be ingested, as third-party webhooks can map to multiple flows or need mapping.

<Tip>
  This documentation will not discuss how the engine works other than stating that it takes the jobs and produces the output. Please refer to [engine](./engine) for more information.
</Tip>

## Sandboxing

Sandbox in Activepieces means in which environment the engine will execute the flow. There are three types of sandboxes, each with different trade-offs:

<Snippet file="execution-mode.mdx" />

### No Sandboxing & V8 Sandboxing

The difference between the two modes is in the execution of code pieces. For V8 Sandboxing, we use [isolated-vm](https://www.npmjs.com/package/isolated-vm), which relies on V8 isolation to isolate code pieces.

These are the steps that are used to execute the flow:

<Steps>
  <Step title="Prepare Code Pieces">
    If the code doesn't exist, it will be compiled using TypeScript Compiler (tsc) and the necessary npm packages will be prepared, if possible.
  </Step>

  <Step title="Install Pieces">
    Pieces are npm packages, we perform a simple check. If they don't exist, we use `pnpm` to install the pieces.
  </Step>

  <Step title="Execution">
    There is a pool of worker threads kept warm and the engine stays running and listening. Each thread executes one engine operation and sends back the result upon completion.
  </Step>
</Steps>

#### Security:

In a self-hosted environment, all piece installations are done by the **platform admin**. It is assumed that the pieces are secure, as they have full access to the machine.

Code pieces provided by the end user are isolated using V8, which restricts the user to browser JavaScript instead of Node.js with npm.

#### Performance

The flow execution is fast as the javascript can be, although there is overhead in polling from queue and prepare the files first time the flow get executed.

#### Benchmark

TBD

### Kernel Namespaces Sandboxing

This consists of two steps: the first one is preparing the sandbox, and the other one is the execution part.

#### Prepare the folder

Each flow will have a folder with everything required to execute this flows, which means the **engine**, **code pieces** and **npms**

<Steps>
  <Step title="Prepare Code Pieces">
    If the code doesn't exist, it will be compiled using TypeScript Compiler (tsc) and the necessary npm packages will be prepared, if possible.
  </Step>

  <Step title="Install Pieces">
    Pieces are npm packages, we perform simple check If they don't exist we use `pnpm` to install the pieces.
  </Step>
</Steps>

#### Execute Flow using Sandbox

In this mode, we use kernel namespaces to isolate everything (file system, memory, CPU). The folder prepared earlier will be bound as a **Read Only** Directory.

Then we use the command line and to spin up the isolation with new node process, something like that.

```bash
./isolate node path/to/flow.js --- rest of args
```

#### Security

The flow execution is isolated in their own namespaces, which means pieces are isolated in different process and namespaces, So the user can run bash scripts and use the file system safely as It's limited and will be removed after the execution, in this mode the user can use any **NPM package** in their code piece.

#### Performance

This mode is **Slow** and **CPU Intensive**. The reason behind this is the **cold boot** of Node.js, since each flow execution will require a new **Node.js** process. The Node.js process consumes a lot of resources and takes some time to compile the code and start executing.

#### Benchmark

TBD


# Environment Variables
Source: https://www.activepieces.com/docs/install/configuration/environment-variables



To configure activepieces, you will need to set some environment variables, There is file called `.env` at the root directory for our main repo.

<Tip> When you execute the [tools/deploy.sh](https://github.com/activepieces/activepieces/blob/main/tools/deploy.sh) script in the Docker installation tutorial,
it will produce these values. </Tip>

## Environment Variables

| Variable                                  | Description                                                                                                                                                                                                                                                                             | Default Value                                          | Example                                                                |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------- |
| `AP_CONFIG_PATH`                          | Optional parameter for specifying the path to store SQLite3 and local settings.                                                                                                                                                                                                         | `~/.activepieces`                                      |                                                                        |
| `AP_CLOUD_AUTH_ENABLED`                   | Turn off the utilization of Activepieces oauth2 applications                                                                                                                                                                                                                            | `false`                                                |                                                                        |
| `AP_DB_TYPE`                              | The type of database to use. (POSTGRES / SQLITE3)                                                                                                                                                                                                                                       | `SQLITE3`                                              |                                                                        |
| `AP_EXECUTION_MODE`                       | You can choose between 'SANDBOXED', 'UNSANDBOXED', 'SANDBOX\_CODE\_ONLY' as possible values. If you decide to change this, make sure to carefully read [https://www.activepieces.com/docs/install/architecture/workers](https://www.activepieces.com/docs/install/architecture/workers) | `UNSANDBOXED`                                          |                                                                        |
| `AP_FLOW_WORKER_CONCURRENCY`              | The number of different flows can be processed in same time                                                                                                                                                                                                                             | `10`                                                   |                                                                        |
| `AP_SCHEDULED_WORKER_CONCURRENCY`         | The number of different scheduled flows can be processed in same time                                                                                                                                                                                                                   | `10`                                                   |                                                                        |
| `AP_ENCRYPTION_KEY`                       | ❗️ Encryption key used for connections is a 32-character (16 bytes) hexadecimal key. You can generate one using the following command: `openssl rand -hex 16`.                                                                                                                          | `None`                                                 |                                                                        |
| `AP_EXECUTION_DATA_RETENTION_DAYS`        | The number of days to retain execution data, logs and events.                                                                                                                                                                                                                           | `30`                                                   |                                                                        |
| `AP_FRONTEND_URL`                         | ❗️ Url that will be used to specify redirect url and webhook url.                                                                                                                                                                                                                       |                                                        |                                                                        |
| `AP_INTERNAL_URL`                         | (BETA) Used to specify the SSO authentication URL.                                                                                                                                                                                                                                      | `None`                                                 | [https://demo.activepieces.com/api](https://demo.activepieces.com/api) |
| `AP_JWT_SECRET`                           | ❗️ Encryption key used for generating JWT tokens is a 32-character hexadecimal key. You can generate one using the following command: `openssl rand -hex 32`.                                                                                                                           | `None`                                                 | [https://demo.activepieces.com](https://demo.activepieces.com)         |
| `AP_QUEUE_MODE`                           | The queue mode to use. (MEMORY / REDIS)                                                                                                                                                                                                                                                 | `MEMORY`                                               |                                                                        |
| `AP_QUEUE_UI_ENABLED`                     | Enable the queue UI (only works with redis)                                                                                                                                                                                                                                             | `true`                                                 |                                                                        |
| `AP_QUEUE_UI_USERNAME`                    | The username for the queue UI. This is required if `AP_QUEUE_UI_ENABLED` is set to `true`.                                                                                                                                                                                              | None                                                   |                                                                        |
| `AP_QUEUE_UI_PASSWORD`                    | The password for the queue UI. This is required if `AP_QUEUE_UI_ENABLED` is set to `true`.                                                                                                                                                                                              | None                                                   |                                                                        |
| `AP_REDIS_FAILED_JOB_RETENTION_DAYS`      | The number of days to retain failed jobs in Redis.                                                                                                                                                                                                                                      | `30`                                                   |                                                                        |
| `AP_REDIS_FAILED_JOB_RETENTION_MAX_COUNT` | The maximum number of failed jobs to retain in Redis.                                                                                                                                                                                                                                   | `2000`                                                 |                                                                        |
| `AP_TRIGGER_DEFAULT_POLL_INTERVAL`        | The default polling interval determines how frequently the system checks for new data updates for pieces with scheduled triggers, such as new Google Contacts.                                                                                                                          | `5`                                                    |                                                                        |
| `AP_PIECES_SOURCE`                        | `AP_PIECES_SOURCE`: `FILE` for local development, `DB` for database. You can find more information about it in [Setting Piece Source](#setting-piece-source) section.                                                                                                                   | `CLOUD_AND_DB`                                         |                                                                        |
| `AP_PIECES_SYNC_MODE`                     | `AP_PIECES_SYNC_MODE`: `NONE` for no metadata syncing / 'OFFICIAL\_AUTO' for automatic syncing for pieces metadata from cloud                                                                                                                                                           | `OFFICIAL_AUTO`                                        |                                                                        |
| `AP_POSTGRES_DATABASE`                    | ❗️ The name of the PostgreSQL database                                                                                                                                                                                                                                                  | `None`                                                 |                                                                        |
| `AP_POSTGRES_HOST`                        | ❗️ The hostname or IP address of the PostgreSQL server                                                                                                                                                                                                                                  | `None`                                                 |                                                                        |
| `AP_POSTGRES_PASSWORD`                    | ❗️ The password for the PostgreSQL,  you can generate a 32-character hexadecimal key using the following command: `openssl rand -hex 32`.                                                                                                                                               | `None`                                                 |                                                                        |
| `AP_POSTGRES_PORT`                        | ❗️ The port number for the PostgreSQL server                                                                                                                                                                                                                                            | `None`                                                 |                                                                        |
| `AP_POSTGRES_USERNAME`                    | ❗️ The username for the PostgreSQL user                                                                                                                                                                                                                                                 | `None`                                                 |                                                                        |
| `AP_POSTGRES_USE_SSL`                     | Use SSL to connect the postgres database                                                                                                                                                                                                                                                | `false`                                                |                                                                        |
| `AP_POSTGRES_SSL_CA`                      | Use SSL Certificate to connect to the postgres database                                                                                                                                                                                                                                 |                                                        |                                                                        |
| `AP_POSTGRES_URL`                         | Alternatively, you can specify only the connection string (e.g postgres\://user:password\@host:5432/database) instead of providing the database, host, port, username, and password.                                                                                                    | `None`                                                 |                                                                        |
| `AP_REDIS_TYPE`                           | Type of Redis, Possible values are `DEFAULT` or `SENTINEL`.                                                                                                                                                                                                                             | `DEFAULT`                                              |                                                                        |
| `AP_REDIS_URL`                            | If a Redis connection URL is specified, all other Redis properties will be ignored.                                                                                                                                                                                                     | `None`                                                 |                                                                        |
| `AP_REDIS_USER`                           | ❗️ Username to use when connect to redis                                                                                                                                                                                                                                                | `None`                                                 |                                                                        |
| `AP_REDIS_PASSWORD`                       | ❗️ Password to use when connect to redis                                                                                                                                                                                                                                                | `None`                                                 |                                                                        |
| `AP_REDIS_HOST`                           | ❗️ The hostname or IP address of the Redis server                                                                                                                                                                                                                                       | `None`                                                 |                                                                        |
| `AP_REDIS_PORT`                           | ❗️ The port number for the Redis server                                                                                                                                                                                                                                                 | `None`                                                 |                                                                        |
| `AP_REDIS_DB`                             | The Redis database index to use                                                                                                                                                                                                                                                         | `0`                                                    |                                                                        |
| `AP_REDIS_USE_SSL`                        | Connect to Redis with SSL                                                                                                                                                                                                                                                               | `false`                                                |                                                                        |
| `AP_REDIS_SSL_CA_FILE`                    | The path to the CA file for the Redis server.                                                                                                                                                                                                                                           | `None`                                                 |                                                                        |
| `AP_REDIS_SENTINEL_HOSTS`                 | If specified, this should be a comma-separated list of `host:port` pairs for Redis Sentinels. Make sure to set `AP_REDIS_CONNECTION_MODE` to `SENTINEL`                                                                                                                                 | `None`                                                 | `sentinel-host-1:26379,sentinel-host-2:26379,sentinel-host-3:26379`    |
| `AP_REDIS_SENTINEL_NAME`                  | The name of the master node monitored by the sentinels.                                                                                                                                                                                                                                 | `None`                                                 | `sentinel-host-1`                                                      |
| `AP_REDIS_SENTINEL_ROLE`                  | The role to connect to, either `master` or `slave`.                                                                                                                                                                                                                                     | `None`                                                 | `master`                                                               |
| `AP_TRIGGER_TIMEOUT_SECONDS`              | Maximum allowed runtime for a trigger to perform polling in seconds                                                                                                                                                                                                                     | `None`                                                 |                                                                        |
| `AP_FLOW_TIMEOUT_SECONDS`                 | Maximum allowed runtime for a flow to run in seconds                                                                                                                                                                                                                                    | `600`                                                  |                                                                        |
| `AP_SANDBOX_PROPAGATED_ENV_VARS`          | Environment variables that will be propagated to the sandboxed code. If you are using it for pieces, we strongly suggests keeping everything in the authentication object to make sure it works across AP instances.                                                                    | `None`                                                 |                                                                        |
| `AP_TELEMETRY_ENABLED`                    | Collect telemetry information.                                                                                                                                                                                                                                                          | `true`                                                 |                                                                        |
| `AP_TEMPLATES_SOURCE_URL`                 | This is the endpoint we query for templates, remove it and templates will be removed from UI                                                                                                                                                                                            | `https://cloud.activepieces.com/api/v1/flow-templates` |                                                                        |
| `AP_WEBHOOK_TIMEOUT_SECONDS`              | The default timeout for webhooks. The maximum allowed is 15 minutes. Please note that Cloudflare limits it to 30 seconds. If you are using a reverse proxy for SSL, make sure it's configured correctly.                                                                                | `30`                                                   |                                                                        |
| `AP_TRIGGER_FAILURE_THRESHOLD`            | The maximum number of consecutive trigger failures is 576 by default, which is equivalent to approximately 2 days.                                                                                                                                                                      | `30`                                                   |                                                                        |
| `AP_PROJECT_RATE_LIMITER_ENABLED`         | Enforce rate limits and prevent excessive usage by a single project.                                                                                                                                                                                                                    | `true`                                                 |                                                                        |
| `AP_MAX_CONCURRENT_JOBS_PER_PROJECT`      | The maximum number of active runs a project can have. This is used to enforce rate limits and prevent excessive usage by a single project.                                                                                                                                              | `100`                                                  |                                                                        |
| `AP_S3_ACCESS_KEY_ID`                     | The access key ID for your S3-compatible storage service. Not required if `AP_S3_USE_IRSA` is `true`.                                                                                                                                                                                   | `None`                                                 |                                                                        |
| `AP_S3_SECRET_ACCESS_KEY`                 | The secret access key for your S3-compatible storage service. Not required if `AP_S3_USE_IRSA` is `true`.                                                                                                                                                                               | `None`                                                 |                                                                        |
| `AP_S3_BUCKET`                            | The name of the S3 bucket to use for file storage.                                                                                                                                                                                                                                      | `None`                                                 |                                                                        |
| `AP_S3_ENDPOINT`                          | The endpoint URL for your S3-compatible storage service. Not required if `AWS_ENDPOINT_URL` is set.                                                                                                                                                                                     | `None`                                                 | `https://s3.amazonaws.com`                                             |
| `AP_S3_REGION`                            | The region where your S3 bucket is located. Not required if `AWS_REGION` is set.                                                                                                                                                                                                        | `None`                                                 | `us-east-1`                                                            |
| `AP_S3_USE_SIGNED_URLS`                   | It is used to route traffic to S3 directly. It should be enabled if the S3 bucket is public.                                                                                                                                                                                            | `None`                                                 |                                                                        |
| `AP_S3_USE_IRSA`                          | Use IAM Role for Service Accounts (IRSA) to connect to S3. When `true`, `AP_S3_ACCESS_KEY_ID` and `AP_S3_ACCESS_KEY_ID` are not required.                                                                                                                                               | `None`                                                 | `true`                                                                 |
| `AP_MAX_FILE_SIZE_MB`                     | The maximum allowed file size in megabytes for uploads including logs of flow runs. If logs exceed this size, they will be truncated which may cause flow execution issues.                                                                                                             | `10`                                                   | `10`                                                                   |
| `AP_FILE_STORAGE_LOCATION`                | The location to store files. Possible values are `DB` for storing files in the database or `S3` for storing files in an S3-compatible storage service.                                                                                                                                  | `DB`                                                   |                                                                        |
| `AP_PAUSED_FLOW_TIMEOUT_DAYS`             | The maximum allowed pause duration in days for a paused flow, please note it can not exceed `AP_EXECUTION_DATA_RETENTION_DAYS`                                                                                                                                                          | `30`                                                   |                                                                        |

<Warning>
  The frontend URL is essential for webhooks and app triggers to work. It must
  be accessible to third parties to send data.
</Warning>

### Setting Webhook (Frontend URL):

The default URL is set to the machine's IP address. To ensure proper operation, ensure that this address is accessible or specify an `AP_FRONTEND_URL` environment variable.

One possible solution for this is using a service like ngrok ([https://ngrok.com/](https://ngrok.com/)), which can be used to expose the frontend port (4200) to the internet.

### Setting Piece Source

These are the different options for the `AP_PIECES_SOURCE` environment variable:

1. `FILE`: **Only for Local Development**, this option loads pieces directly from local files. For Production, please consider using other options, as this one only supports a single version per piece.

2. `DB`: This option will only load pieces that are manually installed in the database from "My Pieces" or the Admin Console in the EE Edition. Pieces are loaded from npm, which provides multiple versions per piece, making it suitable for production.

You can also set AP\_PIECES\_SYNC\_MODE to `OFFICIAL_AUTO`, where it will update the metadata of pieces periodically.

### Redis Configuration

Set the `AP_REDIS_URL` environment variable to the connection URL of your Redis server.

Please note that if a Redis connection URL is specified, all other **Redis properties** will be ignored.

<Info>
  If you don't have the Redis URL, you can use the following command to get it. You can use the following variables:

  * `REDIS_USER`: The username to use when connecting to Redis.
  * `REDIS_PASSWORD`: The password to use when connecting to Redis.
  * `REDIS_HOST`: The hostname or IP address of the Redis server.
  * `REDIS_PORT`: The port number for the Redis server.
  * `REDIS_DB`: The Redis database index to use.
  * `REDIS_USE_SSL`: Connect to Redis with SSL.
</Info>

<Info>
  If you are using **Redis Sentinel**, you can set the following environment variables:

  * `AP_REDIS_TYPE`: Set this to `SENTINEL`.
  * `AP_REDIS_SENTINEL_HOSTS`: A comma-separated list of `host:port` pairs for Redis Sentinels. When set, all other Redis properties will be ignored.
  * `AP_REDIS_SENTINEL_NAME`: The name of the master node monitored by the sentinels.
  * `AP_REDIS_SENTINEL_ROLE`: The role to connect to, either `master` or `slave`.
  * `AP_REDIS_PASSWORD`: The password to use when connecting to Redis.
  * `AP_REDIS_USE_SSL`: Connect to Redis with SSL.
  * `AP_REDIS_SSL_CA_FILE`: The path to the CA file for the Redis server.
</Info>


# Hardware Requirements
Source: https://www.activepieces.com/docs/install/configuration/hardware

Specifications for hosting Activepieces

More information about architecture please visit our [architecture](../architecture/overview) page.

### Technical Specifications

Activepieces is designed to be memory-intensive rather than CPU-intensive. A modest instance will suffice for most scenarios, but requirements can vary based on specific use cases.

| Component    | Memory (RAM) | CPU Cores | Notes                                                                                                                              |
| ------------ | ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| PostgreSQL   | 1 GB         | 1         |                                                                                                                                    |
| Redis        | 1 GB         | 1         |                                                                                                                                    |
| Activepieces | 8 GB         | 2         | For high availability, consider deploying across multiple machines. Set `FLOW_WORKER_CONCURRENCY` to `25` for optimal performance. |

<Tip>
  The above recommendations are designed to meet the needs of the majority of use cases.
</Tip>

## Scaling Factors

### Redis

Redis requires minimal scaling as it primarily stores jobs during processing. Activepieces leverages BullMQ, capable of handling a substantial number of jobs per second.

### PostgreSQL

<Tip>
  **Scaling Tip:** Since files are stored in the database, you can alleviate the load by configuring S3 storage for file management.
</Tip>

PostgreSQL is typically not the system's bottleneck.

### Activepieces Container

<Tip>
  **Scaling Tip:** The Activepieces container is stateless, allowing for seamless horizontal scaling.
</Tip>

* `FLOW_WORKER_CONCURRENCY` and `SCHEDULED_WORKER_CONCURRENCY` dictate the number of concurrent jobs processed for flows and scheduled flows, respectively. By default, these are set to 20 and 10.

## Expected Performance

Activepieces ensures no request is lost; all requests are queued. In the event of a spike, requests will be processed later, which is acceptable as most flows are asynchronous, with synchronous flows being prioritized.

It's hard to predict exact performance because flows can be very different. But running a flow doesn't slow things down, as it runs as fast as regular JavaScript.
(Note: This applies to `SANDBOXED_CODE_ONLY` and `UNSANDBOXED` execution modes, which are recommended and used in self-hosted setups.)

You can anticipate handling over **20 million executions** monthly with this setup.


# Deployment Checklist
Source: https://www.activepieces.com/docs/install/configuration/overview

Checklist to follow after deploying Activepieces

<Info>
  This tutorial assumes you have already followed the quick start guide using one of the installation methods listed in [Install Overview](../overview).
</Info>

In this section, we will go through the checklist after using one of the installation methods and ensure that your deployment is production-ready.

<AccordionGroup>
  <Accordion title="Decide on Sandboxing" icon="code">
    You should decide on the sandboxing mode for your deployment based on your use case and whether it is multi-tenant or not. Here is a simplified way to decide:

    <Tip>
      **Friendly Tip #1**: For multi-tenant setups, use V8/Code Sandboxing.

      It is secure and does not require privileged Docker access in Kubernetes.
      Privileged Docker is usually not allowed to prevent root escalation threats.
    </Tip>

    <Tip>
      **Friendly Tip #2**: For single-tenant setups, use No Sandboxing. It is faster and does not require privileged Docker access.
    </Tip>

    <Snippet file="execution-mode.mdx" />

    More Information at [Sandboxing & Workers](../architecture/workers#sandboxing)
  </Accordion>

  <Accordion title="Enterprise Edition (Optional)" icon="building">
    <Tip>
      For licensing inquiries regarding the self-hosted enterprise edition, please reach out to `sales@activepieces.com`, as the code and Docker image are not covered by the MIT license.
    </Tip>

    <Note>You can request a trial key from within the app or in the cloud by filling out the form. Alternatively, you can contact sales at [https://www.activepieces.com/sales](https://www.activepieces.com/sales).<br />Please know that when your trial runs out, all enterprise [features](/about/editions#feature-comparison) will be shut down meaning any user other than the platform admin will be deactivated, and your private pieces will be deleted, which could result in flows using them to fail.</Note>

    <Warning>
      Enterprise Edition only works on Fresh Installation as the database migration scripts are different from the community edition.
    </Warning>

    <Warning>
      Enterprise edition must use `PostgreSQL` as the database backend and `Redis` as the Queue System.
    </Warning>

    ## Installation

    1. Set the `AP_EDITION` environment variable to `ee`.
    2. Set the `AP_EXECUTION_MODE` to anything other than `UNSANDBOXED`, check the above section.
    3. Once your instance is up, activate the license key by going to Platform Admin -> Setup -> License Keys.

    ![Activation License Key](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/activation-license-key-settings.png)
  </Accordion>

  <Accordion title="Setup HTTPS" icon="lock">
    Setting up HTTPS is highly recommended because many services require webhook URLs to be secure (HTTPS). This helps prevent potential errors.

    To set up SSL, you can use any reverse proxy. For a step-by-step guide, check out our example using [Nginx](./setup-ssl).
  </Accordion>

  <Accordion title="Configure S3 (Optional)" icon="cloud">
    Run logs and files are stored in the database by default, but you can switch to S3 later without any migration; for most cases, the database is enough.

    It's recommended to start with the database and switch to S3 if needed. After switching, expired files in the database will be deleted, and everything will be stored in S3. No manual migration is needed.

    Configure the following environment variables:

    * `AP_S3_ACCESS_KEY_ID`
    * `AP_S3_SECRET_ACCESS_KEY`
    * `AP_S3_ENDPOINT`
    * `AP_S3_BUCKET`
    * `AP_S3_REGION`
    * `AP_MAX_FILE_SIZE_MB`
    * `AP_FILE_STORAGE_LOCATION` (set to `S3`)
    * `AP_S3_USE_SIGNED_URLS`

    <Tip>
      **Friendly Tip #1**: If the S3 bucket supports signed URLs but needs to be accessible over a public network, you can set `AP_S3_USE_SIGNED_URLS` to `true` to route traffic directly to S3 and reduce heavy traffic on your API server.
    </Tip>
  </Accordion>

  <Accordion title="Troubleshooting (Optional)" icon="wrench">
    If you encounter any issues, check out our [Troubleshooting](./troubleshooting) guide.
  </Accordion>
</AccordionGroup>


# Seperate Workers from App
Source: https://www.activepieces.com/docs/install/configuration/seperate-workers



Benefits of separating workers from the main application (APP):

* **Availability**: The application remains lightweight, allowing workers to be scaled independently.
* **Security**: Workers lack direct access to Redis and the database, minimizing impact in case of a security breach.

<Steps>
  <Step title="Create Worker Token">
    To create a worker token, use the local CLI command to generate the JWT and sign it with your `AP_JWT_SECRET` used for the app server. Follow these steps:

    1. Open your terminal and navigate to the root of the repository.
    2. Run the command: `npm run workers token`.
    3. When prompted, enter the JWT secret (this should be the same as the `AP_JWT_SECRET` used for the app server).
    4. The generated token will be displayed in your terminal, copy it and use it in the next step.
       ![Workers Token](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/worker-token.png)
  </Step>

  <Step title="Configure Environment Variables">
    Define the following environment variables in the `.env` file on the worker machine:

    * Set `AP_CONTAINER_TYPE` to `WORKER`
    * Specify `AP_FRONTEND_URL`
    * Provide `AP_WORKER_TOKEN`
  </Step>

  <Step title="Configure Persistent Volume">
    Configure a persistent volume for the worker to cache flows and pieces. This is important as first uncached execution of pieces and flows are very slow. Having a persistent volume significantly improves execution speed.

    Add the following volume mapping to your docker configuration:

    ```yaml
    volumes:
      - <your path>:/usr/src/app/cache
    ```
  </Step>

  <Step title="Launch Worker Machine">
    Launch the worker machine and supply it with the generated token.
  </Step>

  <Step title="Verify Worker Operation">
    Verify that the workers are visible in the Platform Admin Console under Infra -> Workers.
    ![Workers Infrastructure](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/workers.png)
  </Step>

  <Step title="Configure App Container Type">
    On the APP machine, set `AP_CONTAINER_TYPE` to `APP`.
  </Step>
</Steps>


# Setup App Webhooks
Source: https://www.activepieces.com/docs/install/configuration/setup-app-webhooks



Certain apps like Slack and Square only support one webhook per OAuth2 app. This means that manual configuration is required in their developer portal, and it cannot be automated.

## Slack

**Configure Webhook Secret**

1. Visit the "Basic Information" section of your Slack OAuth settings.
2. Copy the "Signing Secret" and save it.
3. Set the following environment variable in your activepieces environment:
   ```
   AP_APP_WEBHOOK_SECRETS={"@activepieces/piece-slack": {"webhookSecret": "SIGNING_SECRET"}}
   ```
4. Restart your application instance.

**Configure Webhook URL**

1. Go to the "Event Subscription" settings in the Slack OAuth2 developer platform.
2. The URL format should be: `https://YOUR_AP_INSTANCE/api/v1/app-events/slack`.
3. When connecting to Slack, use your OAuth2 credentials or update the OAuth2 app details from the admin console (in platform plans).
4. Add the following events to the app:
   * `message.channels`
   * `reaction_added`
   * `message.im`
   * `message.groups`
   * `message.mpim`
   * `app_mention`


# Setup HTTPS
Source: https://www.activepieces.com/docs/install/configuration/setup-ssl



To enable SSL, you can use a reverse proxy. In this case, we will use Nginx as the reverse proxy.

## Install Nginx

```bash
sudo apt-get install nginx
```

## Create Certificate

To proceed with this documentation, it is assumed that you already have a certificate for your domain.

<Tip>
  You have the option to use Cloudflare or generate a certificate using Let's Encrypt or Certbot.
</Tip>

Add the certificate to the following paths: `/etc/key.pem` and `/etc/cert.pem`

## Setup Nginx

```bash
sudo nano /etc/nginx/sites-available/default
```

```bash
server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;

    ssl_certificate /etc/cert.pem;
    ssl_certificate_key /etc/key.pem;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;        
    }
}
```

## Restart Nginx

```bash
sudo systemctl restart nginx
```

## Test

Visit your domain and you should see your application running with SSL.


# Troubleshooting
Source: https://www.activepieces.com/docs/install/configuration/troubleshooting



### Websocket Connection Issues

If you're experiencing issues with websocket connections, it's likely due to incorrect proxy configuration. Common symptoms include:

* Test Flow button not working
* Test step in flows not working
* Copilot features not working
* Real-time updates not showing

To resolve these issues:

1. Ensure your reverse proxy is properly configured for websocket connections
2. Check our [Setup HTTPS](./setup-ssl) guide for correct configuration examples
3. Some browser block http websocket connections, please setup ssl to resolve this issue.

### Runs with Internal Errors or Scheduling Issues

If you're experiencing issues with flow runs showing internal errors or scheduling problems:

[BullBoard dashboard](/handbook/engineering/playbooks/bullboard)

### Truncated logs

If you see `(truncated)` in the flow run logs in your flow runs, it means that the logs have exceeded the maximum allowed file size. You can increase the `AP_MAX_FILE_SIZE_MB` environment variable to a higher value to resolve this issue.

### Reset Password

If you forgot your password on self hosted instance, you can reset it using the following steps:

**Postgres**

1. **Locate PostgreSQL Docker Container**:
   * Use a command like `docker ps` to find the PostgreSQL container.

2. **Access the Container**:
   * Use SSH to access the PostgreSQL Docker container.
   ```bash
   docker exec -it CONTAINER_ID /bin/bash
   ```

3. **Open the PostgreSQL Console**:
   * Inside the container, open the PostgreSQL console with the `psql` command.
   ```bash
   psql -U postgres
   ```

4. **Create a Secure Password**:
   * Use a tool like [bcrypt.online](https://bcrypt.online/) to generate a new secure password, number of rounds is 10.

5. **Update Your Password**:
   * Run the following SQL query within the PostgreSQL console, replacing `HASH_PASSWORD` with your new password and `YOUR_EMAIL_ADDRESS` with your email.
   ```sql
   UPDATE public.user SET password='HASH_PASSWORD' WHERE email='YOUR_EMAIL_ADDRESS';
   ```

**SQLite3**

1. **Open the SQLite3 Shell**:
   * Access the SQLite3 database by opening the SQLite3 shell. Replace "database.db" with the actual name of your SQLite3 database file if it's different.
   ```bash
   sqlite3 ~/.activepieces/database.sqlite
   ```

2. **Create a Secure Password**:
   * Use a tool like [bcrypt.online](https://bcrypt.online/) to generate a new secure password, number of rounds is 10.

3. **Reset Your Password**:
   * Once inside the SQLite3 shell, you can update your password with an SQL query. Replace `HASH_PASSWORD` with your new password and `YOUR_USERNAME` with your username or email.
   ```sql
   UPDATE user SET password = 'HASH_PASSWORD' WHERE email = 'YOUR_EMAIL_ADDRESS';
   ```

4. **Exit the SQLite3 Shell**:
   * After making the changes, exit the SQLite3 shell by typing:
   ```bash
   .exit
   ```


# AWS (Pulumi)
Source: https://www.activepieces.com/docs/install/options/aws

Get Activepieces up & running on AWS with Pulumi for IaC

# Infrastructure-as-Code (IaC) with Pulumi

Pulumi is an IaC solution akin to Terraform or CloudFormation that lets you deploy & manage your infrastructure using popular programming languages e.g. Typescipt (which we'll use), C#, Go etc.

## Deploy from Pulumi Cloud

If you're already familiar with Pulumi Cloud and have [integrated their services with your AWS account](https://www.pulumi.com/docs/pulumi-cloud/deployments/oidc/aws/#configuring-openid-connect-for-aws), you can use the button below to deploy Activepieces in a few clicks.
The template will deploy the latest Activepieces image that's available on [Docker Hub](https://hub.docker.com/r/activepieces/activepieces).

[![Deploy with Pulumi](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/activepieces/activepieces/tree/main/deploy/pulumi)

## Deploy from a local environment

Or, if you're currently using an S3 bucket to maintain your Pulumi state, you can scaffold and deploy Activepieces direct from Docker Hub using the template below in just few commands:

```bash
$ mkdir deploy-activepieces && cd deploy-activepieces 
$ pulumi new https://github.com/activepieces/activepieces/tree/main/deploy/pulumi
$ pulumi up
```

## What's Deployed?

The template is setup to be somewhat flexible, supporting what could be a development or more production-ready configuration.
The configuration options that are presented during stack configuration will allow you to optionally add any or all of:

* PostgreSQL RDS instance. Opting out of this will use a local SQLite3 Db.
* Single node Redis 7 cluster. Opting out of this will mean using an in-memory cache.
* Fully qualified domain name with SSL. Note that the hosted zone must already be configured in Route 53.
  Opting out of this will mean relying on using the application load balancer's url over standard HTTP to access your Activepieces deployment.

For a full list of all the currently available configuration options, take a look at the [Activepieces Pulumi template file on GitHub](https://github.com/activepieces/activepieces/tree/main/deploy/pulumi/Pulumi.yaml).

## Setting up Pulumi for the first time

If you're new to Pulumi then read on to get your local dev environment setup to be able to deploy Activepieces.

### Prerequisites

1. Make sure you have [Node](https://nodejs.org/en/download) and [Pulumi](https://www.pulumi.com/docs/install/) installed.
2. [Install and configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
3. [Install and configure Pulumi](https://www.pulumi.com/docs/clouds/aws/get-started/begin/).
4. Create an S3 bucket which we'll use to maintain the state of all the various service we'll provision for our Activepieces deployment:

```bash
aws s3api create-bucket --bucket pulumi-state --region us-east-1
```

<Tip>
  Note: [Pulumi supports to two different state management approaches](https://www.pulumi.com/docs/concepts/state/#deciding-on-a-state-backend).
  If you'd rather use Pulumi Cloud instead of S3 then feel free to skip this step and setup an account with Pulumi.
</Tip>

5. Login to the Pulumi backend:

```bash
pulumi login s3://pulumi-state?region=us-east-1
```

6. Next we're going to use the Activepieces Pulumi deploy template to create a new project, a stack in that project and then kick off the deploy:

```bash
$ mkdir deploy-activepieces && cd deploy-activepieces 
$ pulumi new https://github.com/activepieces/activepieces/tree/main/deploy/pulumi
```

This step will prompt you to create you stack and to populate a series of config options, such as whether or not to provision a PostgreSQL RDS instance or use SQLite3.

<Tip>
  Note: When choosing a stack name, use something descriptive like `activepieces-dev`, `ap-prod` etc.
  This solution uses the stack name as a prefix for every AWS service created\
  e.g. your VPC will be named `<stack name>-vpc`.
</Tip>

7. Nothing left to do now but kick off the deploy:

```bash
pulumi up
```

8. Now choose `yes` when prompted. Once the deployment has finished, you should see a bunch of Pulumi output variables that look like the following:

```json
    _: {
        activePiecesUrl: "http://<alb name & id>.us-east-1.elb.amazonaws.com"
        activepiecesEnv: [
         . . . .
        ]
       }
```

The config value of interest here is the `activePiecesUrl` as that is the URL for our Activepieces deployment.
If you chose to add a fully qualified domain during your stack configuration, that will be displayed here.
Otherwise you'll see the URL to the application load balancer. And that's it.

Congratulations! You have successfully deployed Activepieces to AWS.

## Deploy a locally built Activepieces Docker image

To deploy a locally built image instead of using the official Docker Hub image, read on.

1. Clone the Activepieces repo locally:

```bash
git clone https://github.com/activepieces/activepieces
```

2. Move into the `deploy/pulumi` folder & install the necessary npm packages:

```bash
cd deploy/pulumi && npm i
```

3. This folder already has two Pulumi stack configuration files reday to go: `Pulumi.activepieces-dev.yaml` and `Pulumi.activepieces-prod.yaml`.
   These files already contain all the configurations we need to create our environments. Feel free to have a look & edit the values as you see fit.
   Lets continue by creating a development stack that uses the existing `Pulumi.activepieces-dev.yaml` file & kick off the deploy.

```bash
pulumi stack init activepieces-dev && pulumi up
```

<Tip>
  Note: Using `activepieces-dev` or `activepieces-prod` for the `pulumi stack init` command is required here as the stack name needs to match the existing stack file name in the folder.
</Tip>

4. You should now see a preview in the terminal of all the services that will be provisioned, before you continue.
   Once you choose `yes`, a new image will be built based on the `Dockerfile` in the root of the solution (make sure Docker Desktop is running) and then pushed up to a new ECR, along with provisioning all the other AWS services for the stack.

Congratulations! You have successfully deployed Activepieces into AWS using a locally built Docker image.

## Customising the deploy

All of the current configuration options, as well as the low-level details associated with the provisioned services are fully customisable, as you would expect from any IaC.
For example, if you'd like to have three availability zones instead of two for the VPC, use an older version of Redis or add some additional security group rules for PostgreSQL, you can update all of these and more in the `index.ts` file inside the `deploy` folder.

Or maybe you'd still like to deploy the official Activepieces Docker image instead of a local build, but would like to change some of the services. Simply set the `deployLocalBuild` config option in the stack file to `false` and make whatever changes you'd like to the `index.ts` file.

Checking out the [Pulumi docs](https://www.pulumi.com/docs/clouds/aws/) before doing so is highly encouraged.


# Docker
Source: https://www.activepieces.com/docs/install/options/docker

Single docker image deployment with SQLite3 and Memory Queue

<Tip>
  Set up Activepieces using Docker Compose for easy deployment - Ideal for personal and testing with SQLite3 and in-memory queue.
  For production (companies), use PostgreSQL and Redis, Refer to docker compose setup.
</Tip>

To get up and running quickly with Activepieces, we will use the Activepieces Docker image. Follow these steps:

## Prerequisites

You need to have [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Docker](https://docs.docker.com/get-docker/) installed on your machine in order to set up Activepieces via Docker Compose.

## Install

### Pull Image and Run Docker image

Pull the Activepieces Docker image and run the container with the following command:

```bash
docker run -d -p 8080:80 -v ~/.activepieces:/root/.activepieces -e AP_QUEUE_MODE=MEMORY -e AP_DB_TYPE=SQLITE3 -e AP_FRONTEND_URL="http://localhost:8080" activepieces/activepieces:latest
```

### Configure Webhook URL (Important for Triggers, Optional If you have public IP)

**Note:** By default, Activepieces will try to use your public IP for webhooks. If you are self-hosting on a personal machine, you must configure the frontend URL so that the webhook is accessible from the internet.

**Optional:** The easiest way to expose your webhook URL on localhost is by using a service like ngrok. However, it is not suitable for production use.

1. Install ngrok
2. Run the following command:

```bash
ngrok http 8080
```

3. Replace `AP_FRONTEND_URL` environment variable in the command line above.

![Ngrok](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/docker-ngrok.png)

## Upgrade

Please follow the steps below:

### Step 1: Back Up Your Data (Recommended)

Before proceeding with the upgrade, it is always a good practice to back up your Activepieces data to avoid any potential data loss during the update process.

1. **Stop the Current Activepieces Container:** If your Activepieces container is running, stop it using the following command:
   ```bash
   docker stop activepieces_container_name
   ```

2. **Backup Activepieces Data Directory:** By default, Activepieces data is stored in the `~/.activepieces` directory on your host machine. Create a backup of this directory to a safe location using the following command:
   ```bash
   cp -r ~/.activepieces ~/.activepieces_backup
   ```

### Step 2: Update the Docker Image

1. **Pull the Latest Activepieces Docker Image:** Run the following command to pull the latest Activepieces Docker image from Docker Hub:
   ```bash
   docker pull activepieces/activepieces:latest
   ```

### Step 3: Remove the Existing Activepieces Container

1. **Stop and Remove the Current Activepieces Container:** If your Activepieces container is running, stop and remove it using the following commands:
   ```bash
   docker stop activepieces_container_name
   docker rm activepieces_container_name
   ```

### Step 4: Run the Updated Activepieces Container

Now, run the updated Activepieces container with the latest image using the same command you used during the initial setup. Be sure to replace `activepieces_container_name` with the desired name for your new container.

```bash
docker run -d -p 8080:80 -v ~/.activepieces:/root/.activepieces -e AP_QUEUE_MODE=MEMORY -e AP_DB_TYPE=SQLITE3 -e AP_FRONTEND_URL="http://localhost:8080" --name activepieces_container_name activepieces/activepieces:latest
```

Congratulations! You have successfully upgraded your Activepieces Docker deployment


# Docker Compose
Source: https://www.activepieces.com/docs/install/options/docker-compose



To get up and running quickly with Activepieces, we will use the Activepieces Docker image. Follow these steps:

## Prerequisites

You need to have [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Docker](https://docs.docker.com/get-docker/) installed on your machine in order to set up Activepieces via Docker Compose.

## Installing

**1. Clone Activepieces repository.**

Use the command line to clone Activepieces repository:

```bash
git clone https://github.com/activepieces/activepieces.git
```

**2. Go to the repository folder.**

```bash
cd activepieces
```

**3.Generate Environment variable**

Run the following command from the command prompt / terminal

```bash
sh tools/deploy.sh
```

<Tip>
  If none of the above methods work, you can rename the .env.example file in the root directory to .env and fill in the necessary information within the file.
</Tip>

**4. Run Activepieces.**

<Warning>
  Please note that "docker-compose" (with a dash) is an outdated version of Docker Compose and it will not work properly. We strongly recommend downloading and installing version 2 from the [here](https://docs.docker.com/compose/install/) to use Docker Compose.
</Warning>

```bash
docker compose -p activepieces up
```

## 4. Configure Webhook URL (Important for Triggers, Optional If you have public IP)

**Note:** By default, Activepieces will try to use your public IP for webhooks. If you are self-hosting on a personal machine, you must configure the frontend URL so that the webhook is accessible from the internet.

**Optional:** The easiest way to expose your webhook URL on localhost is by using a service like ngrok. However, it is not suitable for production use.

1. Install ngrok
2. Run the following command:

```bash
ngrok http 8080
```

3. Replace `AP_FRONTEND_URL` environment variable in `.env` with the ngrok url.

![Ngrok](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/docker-ngrok.png)

<Warning>
  When deploying for production, ensure that you update the database credentials and properly set the environment variables.

  Review the [configurations guide](/install/configuration/environment-variables) to make any necessary adjustments.
</Warning>

## Upgrading

To upgrade to new versions, which are installed using docker compose, perform the following steps. First, open a terminal in the activepieces repository directory and run the following commands.

### Automatic Pull

**1. Run the update script**

```bash
sh tools/update.sh
```

### Manually Pull

**1. Pull the new docker compose file**

```bash
git pull
```

**2. Pull the new images**

```bash
docker compose pull
```

**3. Review changelog for breaking changes**

<Warning>
  Please review breaking changes in the [changelog](../../about/breaking-changes).
</Warning>

**4. Run the updated docker images**

```
docker compose up -d --remove-orphans
```

Congratulations! You have now successfully updated the version.

## Deleting

The following command is capable of deleting all Docker containers and associated data, and therefore should be used with caution:

```
sh tools/reset.sh
```

<Warning>
  Executing this command will result in the removal of all Docker containers and the data stored within them. It is important to be aware of the potentially hazardous nature of this command before proceeding.
</Warning>


# Easypanel
Source: https://www.activepieces.com/docs/install/options/easypanel

Run Activepieces with Easypanel 1-Click Install

Easypanel is a modern server control panel. If you [run Easypanel](https://easypanel.io/docs) on your server, you can deploy Activepieces with 1 click on it.

<a target="_blank" rel="noopener" href="https://easypanel.io/docs/templates/activepieces">![Deploy to Easypanel](https://easypanel.io/img/deploy-on-easypanel-40.svg)</a>

## Instructions

1. Create a VM that runs Ubuntu on your cloud provider.
2. Install Easypanel using the instructions from the website.
3. Create a new project.
4. Install Activepieces using the dedicated template.


# Elestio
Source: https://www.activepieces.com/docs/install/options/elestio

Run Activepieces with Elestio 1-Click Install

You can deploy Activepieces on Elestio using one-click deployment. Elestio handles version updates, maintenance, security, backups, etc. So go ahead and click below to deploy and start using.

[![Deploy on Elestio](https://elest.io/images/logos/deploy-to-elestio-btn.png)](https://elest.io/open-source/activepieces)


# GCP
Source: https://www.activepieces.com/docs/install/options/gcp



This documentation is to deploy activepieces on VM Instance or VM Instance Group, we should first create VM template

## Create VM Template

First choose machine type (e.g e2-medium)

After configuring the VM Template, you can proceed to click on "Deploy Container" and specify the following container-specific settings:

* Image: activepieces/activepieces
* Run as a privileged container: true
* Environment Variables:
  * `AP_QUEUE_MODE`: MEMORY
  * `AP_DB_TYPE`: SQLITE3
  * `AP_FRONTEND_URL`: [http://localhost:80](http://localhost:80)
  * `AP_EXECUTION_MODE`: SANDBOXED
* Firewall: Allow HTTP traffic (for testing purposes only)

Once these details are entered, click on the "Deploy" button and patiently wait for the container deployment process to complete.\\

After a successful deployment, you can access the ActivePieces application by visiting the external IP address of the VM on GCP.

## Production Deployment

Please visit [ActivePieces](/install/configuration/environment-variables) for more details on how to customize the application.


# Overview
Source: https://www.activepieces.com/docs/install/overview

Introduction to the different ways to install Activepieces

Activepieces Community Edition can be deployed using **Docker**, **Docker Compose**, and **Kubernetes**.

<Tip>
  Community Edition is **free** and **open source**.

  You can read the difference between the editions [here](../about/editions).
</Tip>

## Recommended Options

<CardGroup cols={2}>
  <Card title="Docker (Fastest)" icon="docker" color="#248fe0" href="./options/docker">
    Deploy Activepieces as a single Docker container using the SQLite database.
  </Card>

  <Card title="Docker Compose" icon="layer-group" color="#00FFFF" href="./options/docker-compose">
    Deploy Activepieces with **Redis** and **PostgreSQL** setup.
  </Card>
</CardGroup>

## Other Options

<CardGroup cols={2}>
  <Card
    title="Easypanel"
    icon={
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 245 245">
        <g clip-path="url(#a)">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M242.291 110.378a15.002 15.002 0 0 0 0-15l-48.077-83.272a15.002 15.002 0 0 0-12.991-7.5H85.07a15 15 0 0 0-12.99 7.5L41.071 65.812a.015.015 0 0 0-.013.008L2.462 132.673a15 15 0 0 0 0 15l48.077 83.272a15 15 0 0 0 12.99 7.5h96.154a15.002 15.002 0 0 0 12.991-7.5l31.007-53.706c.005 0 .01-.003.013-.007l38.598-66.854Zm-38.611 66.861 3.265-5.655a15.002 15.002 0 0 0 0-15l-48.077-83.272a14.999 14.999 0 0 0-12.99-7.5H41.072l-3.265 5.656a15 15 0 0 0 0 15l48.077 83.271a15 15 0 0 0 12.99 7.5H203.68Z" fill="url(#b)" />
        </g>
        <defs>
          <linearGradient id="b" x1="188.72" y1="6.614" x2="56.032" y2="236.437" gradientUnits="userSpaceOnUse">
            <stop stop-color="#12CD87" />
            <stop offset="1" stop-color="#12ABCD" />
          </linearGradient>
          <clipPath id="a">
            <path fill="#fff" d="M0 0h245v245H0z" />
          </clipPath>
        </defs>
      </svg>
      }
    href="./options/easypanel"
  >
    1-Click Install with Easypanel template, maintained by the community.
  </Card>

  <Card title="Elestio" icon="cloud" color="#ff9900" href="./options/elestio">
    1-Click Install on Elestio.
  </Card>

  <Card title="AWS (Pulumi)" icon="aws" color="#ff9900" href="./options/aws">
    Install on AWS with Pulumi.
  </Card>

  <Card title="GCP" icon="cloud" color="#4385f5" href="./options/gcp">
    Install on GCP as a VM template.
  </Card>

  <Card
    title="PikaPods"
    icon={
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 402.2 402.2">
  <path d="M393 277c-3 7-8 9-15 9H66c-27 0-49-18-55-45a56 56 0 0 1 54-68c7 0 12-5 12-11s-5-11-12-11H22c-7 0-12-5-12-11 0-7 4-12 12-12h44c18 1 33 15 33 33 1 19-14 34-33 35-18 0-31 12-34 30-2 16 9 35 31 37h37c5-46 26-83 65-110 22-15 47-23 74-24l-4 16c-4 30 19 58 49 61l8 1c6-1 11-6 10-12 0-6-5-10-11-10-14-1-24-7-30-20-7-12-4-27 5-37s24-14 36-10c13 5 22 17 23 31l2 4c33 23 55 54 63 93l3 17v14m-57-59c0-6-5-11-11-11s-12 5-12 11 6 12 12 12c6-1 11-6 11-12" 
        fill="#4daf4e"/>
</svg>
}
    href="https://www.pikapods.com/pods?run=activepieces"
  >
    Instantly run on PikaPods from \$2.9/month.
  </Card>

  <Card title="RepoCloud" icon="cloud" href="https://repocloud.io/details/?app_id=177">
    Easily install on RepoCloud using this template, maintained by the community.
  </Card>

  <Card
    title="Zeabur"
    icon={
  <svg viewBox="0 0 294 229" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M113.865 144.888H293.087V229H0V144.888H82.388L195.822 84.112H0V0H293.087V84.112L113.865 144.888Z" fill="black"/>
    <path d="M194.847 0H0V84.112H194.847V0Z" fill="#6300FF"/>
    <path d="M293.065 144.888H114.772V229H293.065V144.888Z" fill="#FF4400"/>
  </svg>
}
    href="https://zeabur.com/templates/LNTQDF"
  >
    1-Click Install on Zeabur.
  </Card>
</CardGroup>

## Cloud Edition

<CardGroup cols={2}>
  <Card title="Activepieces Cloud" icon="cloud" color="##5155D7" href="https://cloud.activepieces.com/">
    This is the fastest option.
  </Card>
</CardGroup>


# Connection Deleted
Source: https://www.activepieces.com/docs/operations/audit-logs/connection-deleted





# Connection Upserted
Source: https://www.activepieces.com/docs/operations/audit-logs/connection-upserted





# Flow Created
Source: https://www.activepieces.com/docs/operations/audit-logs/flow-created





# Flow Deleted
Source: https://www.activepieces.com/docs/operations/audit-logs/flow-deleted





# Flow Run Finished
Source: https://www.activepieces.com/docs/operations/audit-logs/flow-run-finished





# Flow Run Started
Source: https://www.activepieces.com/docs/operations/audit-logs/flow-run-started





# Flow Updated
Source: https://www.activepieces.com/docs/operations/audit-logs/flow-updated





# Folder Created
Source: https://www.activepieces.com/docs/operations/audit-logs/folder-created





# Folder Deleted
Source: https://www.activepieces.com/docs/operations/audit-logs/folder-deleted





# Folder Updated
Source: https://www.activepieces.com/docs/operations/audit-logs/folder-updated





# Overview
Source: https://www.activepieces.com/docs/operations/audit-logs/overview



<Snippet file="enterprise-feature.mdx" />

This table in admin console contains all application events. We are constantly adding new events, so there is no better place to see the events defined in the code than [here](https://github.com/activepieces/activepieces/blob/main/packages/ee/shared/src/lib/audit-events/index.ts).

![Audit Logs](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/audit-logs.png)


# Signing Key Created
Source: https://www.activepieces.com/docs/operations/audit-logs/signing-key-created





# User Email Verified
Source: https://www.activepieces.com/docs/operations/audit-logs/user-email-verified





# User Password Reset
Source: https://www.activepieces.com/docs/operations/audit-logs/user-password-reset





# User Signed In
Source: https://www.activepieces.com/docs/operations/audit-logs/user-signed-in





# User Signed Up
Source: https://www.activepieces.com/docs/operations/audit-logs/user-signed-up





# Environments & Releases
Source: https://www.activepieces.com/docs/operations/git-sync



<Snippet file="enterprise-feature.mdx" />

The Project Releases feature allows for the creation of an **external backup**, **environments**, and maintaining a **version history** from the Git Repository or an existing project.

### How It Works

This example explains how to set up development and production environments using either Git repositories or existing projects as sources. The setup can be extended to include multiple environments, Git branches, or projects based on your needs.

### Requirements

You have to enable the project releases feature in the Settings -> Environments.

## Git-Sync

**Requirements**

* Empty Git Repository
* Two Projects in Activepieces: one for Development and one for Production

### 1. Push Flow to Repository

After making changes in the flow:

1. Click the 3-dot menu near the flow name
2. Select "Push to Git"
3. Add commit message and push

### 2. Deleting Flows

When you delete a flow from a project configured with Git sync (Release from Git), it will automatically delete the flow from the repository.

## Project-Sync

### 1. **Initialize Projects**

* Create a source project (e.g., Development)
* Create a target project (e.g., Production)

### 2. **Develop**

* Build and test your flows in the source project
* When ready, sync changes to the target project using releases

## Creating a Release

<Note>
  Credentials are not synced automatically. Create identical credentials with the same names in both environments manually.
</Note>

You can create a release in two ways:

1. **From Git Repository**:
   * Click "Create Release" and select "From Git"

2. **From Existing Project**:
   * Click "Create Release" and select "From Project"
   * Choose the source project to sync from

For both methods:

* Review the changes between environments
* Choose the operations you want to perform:
  * **Update Existing Flows**: Synchronize flows that exist in both environments
  * **Delete Missing Flows**: Remove flows that are no longer present in the source
  * **Create New Flows**: Add new flows found in the source
* Confirm to create the release

### Important Notes

* Enabled flows will be updated and republished (failed republishes become drafts)
* New flows start in a disabled state

### Approval Workflow (Optional)

To manage your approval workflow, you can use Git by creating two branches: development and production. Then, you can use standard pull requests as the approval step.

### GitHub action

This GitHub action can be used to automatically pull changes upon merging.

<Tip>
  Don't forget to replace `INSTANCE_URL` and `PROJECT_ID`, and add `ACTIVEPIECES_API_KEY` to the secrets.
</Tip>

```yml
name: Auto Deploy
on:
  workflow_dispatch:
  push:
    branches: [ "main" ]
jobs:
  run-pull:
    runs-on: ubuntu-latest
    steps:
      - name: deploy
        # Use GitHub secrets
        run: |
          curl --request POST \
            --url {INSTANCE_URL}/api/v1/git-repos/pull \
            --header 'Authorization: Bearer ${{ secrets.ACTIVEPIECES_API_KEY }}' \
            --header 'Content-Type: application/json' \
            --data '{
              "projectId": "{PROJECT_ID}"
            }'
```


# Project Permissions
Source: https://www.activepieces.com/docs/security/permissions

Documentation on project permissions in Activepieces

Activepieces utilizes Role-Based Access Control (RBAC) for managing permissions within projects. Each project consists of multiple flows and users, with each user assigned specific roles that define their actions within the project.

The supported roles in Activepieces are:

* **Admin:**
  * View Flows
  * Edit Flows
  * Publish/Turn On and Off Flows
  * View Runs
  * Retry Runs
  * View Issues
  * Resolve Issues
  * View Connections
  * Edit Connections
  * View Project Members
  * Add/Remove Project Members
  * Configure Git Repo to Sync Flows With
  * Push/Pull Flows to/from Git Repo

* **Editor:**
  * View Flows
  * Edit Flows
  * Publish/Turn On and Off Flows
  * View Runs
  * Retry Runs
  * View Connections
  * Edit Connections
  * View Issues
  * Resolve Issues
  * View Project Members

* **Operator:**
  * Publish/Turn On and Off Flows
  * View Runs
  * Retry Runs
  * View Issues
  * View Connections
  * Edit Connections
  * View Project Members

* **Viewer:**
  * View Flows
  * View Runs
  * View Connections
  * View Project Members
  * View Issues


# Security & Data Practices
Source: https://www.activepieces.com/docs/security/practices

We prioritize security and follow these practices to keep information safe.

## External Systems Credentials

**Storing Credentials**

All credentials are stored with 256-bit encryption keys, and there is no API to retrieve them for the user. They are sent only during processing, after which access is revoked from the engine.

**Data Masking**

We implement a robust data masking mechanism where third-party credentials or any sensitive information are systematically censored within the logs, guaranteeing that sensitive information is never stored or documented.

**OAuth2**

Integrations with third parties are always done using OAuth2, with a limited number of scopes when third-party support allows.

## Vulnerability Disclosure

Activepieces is an open-source project that welcomes contributors to test and report security issues.

For detailed information about our security policy, please refer to our GitHub Security Policy at: [https://github.com/activepieces/activepieces/security/policy](https://github.com/activepieces/activepieces/security/policy)

## Access and Authentication

**Role-Based Access Control (RBAC)**

To manage user access, we utilize Role-Based Access Control (RBAC). Team admins assign roles to users, granting them specific permissions to access and interact with projects, folders, and resources. RBAC allows for fine-grained control, enabling administrators to define and enforce access policies based on user roles.

**Single Sign-On (SSO)**

Implementing Single Sign-On (SSO) serves as a pivotal component of our security strategy. SSO streamlines user authentication by allowing them to access Activepieces with a single set of credentials. This not only enhances user convenience but also strengthens security by reducing the potential attack surface associated with managing multiple login credentials.

**Audit Logs**

We maintain comprehensive audit logs to track and monitor all access activities within Activepieces. This includes user interactions, system changes, and other relevant events. Our meticulous logging helps identify security threats and ensures transparency and accountability in our security measures.

**Password Policy Enforcement**

Users log in to Activepieces using a password known only to them. Activepieces enforces password length and complexity standards. Passwords are not stored; instead, only a secure hash of the password is stored in the database. For more information.

## Privacy & Data

**Supported Cloud Regions**

Presently, our cloud services are available in Germany as the supported data region.

We have plans to expand to additional regions in the near future.
If you opt for **self-hosting**, the available regions will depend on where you choose to host.

**Policy**

To better understand how we handle your data and prioritize your privacy, please take a moment to review our [Privacy Policy](https://www.activepieces.com/privacy). This document outlines in detail the measures we take to safeguard your information and the principles guiding our approach to privacy and data protection.


# Single Sign-On
Source: https://www.activepieces.com/docs/security/sso



<Snippet file="enterprise-feature.mdx" />

## Enforcing SSO

You can enforce SSO by specifying the domain. As part of the SSO configuration, you have the option to disable email and user login. This ensures that all authentication is routed through the designated SSO provider.

![SSO](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/sso.png)

## Supported SSO Providers

You can enable various SSO providers, including Google and GitHub, to integrate with your system by configuring SSO.

### Google:

<Steps>
  <Step title="Go to the Developer Console" />

  <Step title="Create an OAuth2 App" />

  <Step title="Copy the Redirect URL from the Configure Screen into the Google App" />

  <Step title="Fill in the Client ID & Client Secret in Activepieces" />

  <Step title="Click Finish" />
</Steps>

### GitHub:

<Steps>
  <Step title="Go to the GitHub Developer Settings" />

  <Step title="Create a new OAuth App" />

  <Step title="Fill in the App details and click Register a new application" />

  <Step title="Use the following Redirect URL from the Configure Screen" />

  <Step title="Fill in the Homepage URL with the URL of your application" />

  <Step title="Click Register application" />

  <Step title="Copy the Client ID and Client Secret and fill them in Activepieces" />

  <Step title="Click Finish" />
</Steps>

### SAML with OKTA:

<Steps>
  <Step title="Go to the Okta Admin Portal and create a new app" />

  <Step title="Select SAML 2.0 as the Sign-on method" />

  <Step title="Fill in the App details and click Next" />

  <Step title="Use the following Single Sign-On URL from the Configure Screen" />

  <Step title="Fill in Audience URI (SP Entity ID) with 'Activepieces'" />

  <Step title="Add the following attributes (firstName, lastName, email)" />

  <Step title="Click Next and Finish" />

  <Step title="Go to the Sign On tab and click on View Setup Instructions" />

  <Step title="Copy the Identity Provider metadata and paste it in the Idp Metadata field" />

  <Step title="Copy the Signing Certificate and paste it in the Signing Key field" />

  <Step title="Click Save" />
</Steps>

### SAML with JumpCloud:

<Steps>
  <Step title="Go to the JumpCloud Admin Portal and create a new app" />

  <Step title="Create SAML App" />

  <Step title="Copy the ACS URL from Activepieces and paste it in the ACS urls">
    ![JumpCloud ACS URL](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/jumpcloud/acl-url.png)
  </Step>

  <Step title="Fill in Audience URI (SP Entity ID) with 'Activepieces'" />

  <Step title="Add the following attributes (firstName, lastName, email)">
    ![JumpCloud User Attributes](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/jumpcloud/user-attribute.png)
  </Step>

  <Step title="Include the HTTP-Redirect binding and export the metadata">
    JumpCloud does not provide the `HTTP-Redirect` binding by default. You need to tick this box.
    ![JumpCloud Redirect Binding](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/jumpcloud/declare-login.png)

    Make sure you press `Save` and then Refresh the Page and Click on `Export Metadata`

    ![JumpCloud Export Metadata](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/jumpcloud/export-metadata.png)

    <Tip>
      Please Verify ` Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"` inside the xml.
    </Tip>

    After you export the metadata, paste it in the `Idp Metadata` field.
  </Step>

  <Step title="Copy the Certificate and paste it in the Signing Key field">
    Find the `<ds:X509Certificate>` element in the IDP metadata and copy its value. Paste it between these lines:

    ```
    -----BEGIN CERTIFICATE-----
    [PASTE THE VALUE FROM IDP METADATA]
    -----END CERTIFICATE-----
    ```
  </Step>

  <Step title="Make sure you Assigned the App to the User">
    ![JumpCloud Assign App](https://mintlify.s3.us-west-1.amazonaws.com/activepieces/resources/screenshots/jumpcloud/user-groups.png)
  </Step>

  <Step title="Click Next and Finish" />
</Steps>


