# Get stats
Source: https://docs.typebot.com/api-reference/analytics/get-stats
builder GET /v1/typebots/{typebotId}/analytics/stats
# Authentication
Source: https://docs.typebot.com/api-reference/authentication
Some API endpoints are protected, and therefore require that you authenticate using an API token.
## Generate a token
1. Navigate to your typebot dashboard ([https://app.typebot.io/typebots](https://app.typebot.io/typebots))
2. Click on Settings & Members > My account
3. Under the "API tokens" section, click on "Create"
4. Give it a name, then click on "Create token"
5. Copy your token.
## Use your token
You can authenticate by adding an `Authorization` header to all your HTTP calls. The Authorization header is formatted as such: `Authorization: Bearer ` (replace `` with your token previously generated).
Example:
```sh theme={null}
curl -L -X GET 'https://app.typebot.io/api/typebots/:typebotId/results' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer myAwesomeToken'
```
# Get current usage
Source: https://docs.typebot.com/api-reference/billing/get-usage
GET /v1/billing/usage
# List invoices
Source: https://docs.typebot.com/api-reference/billing/list-invoices
GET /v1/billing/invoices
# Continue chat
Source: https://docs.typebot.com/api-reference/chat/continue-chat
openapi/viewer.json POST /v1/sessions/{sessionId}/continueChat
# Generate upload URL
Source: https://docs.typebot.com/api-reference/chat/generate-upload-url
openapi/viewer.json POST /v3/generate-upload-url
Used to upload anything from the client to S3 bucket
The `presignedUrl` and `formData` fields can be then used to upload the file to the S3 bucket, directly from the browser if necessary. Here is an example:
```js theme={null}
// data contains the presignedUrl and formData fields from the response
let upload
if (data.formData && Object.keys(data.formData).length > 0) {
const formData = new FormData()
Object.entries(data.formData).forEach(([key, value]) => {
formData.append(key, value)
})
formData.append('file', file)
upload = await fetch(data.presignedUrl, {
method: 'POST',
body: formData,
})
} else {
upload = await fetch(data.presignedUrl, {
method: 'PUT',
body: file,
headers: {
'Content-Type': file.type,
},
})
}
```
# Save logs
Source: https://docs.typebot.com/api-reference/chat/save-logs
POST /v2/sessions/{sessionId}/clientLogs
# Start chat
Source: https://docs.typebot.com/api-reference/chat/start-chat
POST /v1/typebots/{publicId}/startChat
# Start preview chat
Source: https://docs.typebot.com/api-reference/chat/start-preview-chat
openapi/viewer.json POST /v1/typebots/{typebotId}/preview/startChat
Use this endpoint to test your bot. The answers will not be saved. And some blocks like "Send email" will be skipped.
# Update typebot in session
Source: https://docs.typebot.com/api-reference/chat/update-typebot-in-session
POST /v1/sessions/{sessionId}/updateTypebot
Update chat session with latest typebot modifications. This is useful when you want to update the typebot in an ongoing session after making changes to it.
# Create a folder
Source: https://docs.typebot.com/api-reference/folder/create
POST /v1/folders
# Delete a folder
Source: https://docs.typebot.com/api-reference/folder/delete
DELETE /v1/folders/{folderId}
# Get a folder
Source: https://docs.typebot.com/api-reference/folder/get
GET /v1/folders/{folderId}
# List folders
Source: https://docs.typebot.com/api-reference/folder/list
GET /v1/folders
# Update a folder
Source: https://docs.typebot.com/api-reference/folder/update
PATCH /v1/folders/{folderId}
# How-to
Source: https://docs.typebot.com/api-reference/how-to
### How to find my `typebotId`
If you'd like to execute the typebot in preview mode, you will need to provide the ID of the building typebot available in the editor URL:
### How to find my `publicId`
For published typebot execution, you need to provide the public typebot ID available here:
### How to find my `workspaceId`
In your workspace dashboard, head over to `Settings & Members > Workspace > Settings` and copy the workspace ID
### How to handle stream
If you enabled stream, whenever a AI message should be streamed, you will receive that kind of JSON response:
```json theme={null}
{
"messages": [],
"clientSideActions": [
{
"type": "stream",
"stream": true,
"expectsDedicatedReply": true
}
]
}
```
The bot is ready to accept the message streaming. You now need to send the following query:
```sh theme={null}
curl -X POST https://typebot.co/api/v2/sessions/{sessionId}/streamMessage
```
Where `{sessionId}` should be replaced by the session ID you got from the start chat response.
This endpoint will send Server-Sent events with all the information to display the streamed message.
Once it is done, you can contine the flow by sending a [continue chat request](./chat/continue-chat) with the streamed message as the message content.
# Delete results
Source: https://docs.typebot.com/api-reference/results/delete
DELETE /v1/typebots/{typebotId}/results
# Get a result
Source: https://docs.typebot.com/api-reference/results/get
GET /v1/typebots/{typebotId}/results/{resultId}
# List results
Source: https://docs.typebot.com/api-reference/results/list
GET /v1/typebots/{typebotId}/results
# List logs in result
Source: https://docs.typebot.com/api-reference/results/list-logs
GET /v1/typebots/{typebotId}/results/{resultId}/logs
# Create a typebot
Source: https://docs.typebot.com/api-reference/typebot/create
POST /v1/typebots
# Delete a typebot
Source: https://docs.typebot.com/api-reference/typebot/delete
DELETE /v1/typebots/{typebotId}
# Get a typebot
Source: https://docs.typebot.com/api-reference/typebot/get
GET /v1/typebots/{typebotId}
# Get published bot
Source: https://docs.typebot.com/api-reference/typebot/get-published-bot
GET /v1/typebots/{typebotId}/publishedTypebot
# Import a typebot
Source: https://docs.typebot.com/api-reference/typebot/import
POST /v1/typebots/import
# List typebots
Source: https://docs.typebot.com/api-reference/typebot/list
GET /v1/typebots
# Publish typebot
Source: https://docs.typebot.com/api-reference/typebot/publish
POST /v1/typebots/{typebotId}/publish
# Unpublish typebot
Source: https://docs.typebot.com/api-reference/typebot/unpublish
POST /v1/typebots/{typebotId}/unpublish
# Update a typebot
Source: https://docs.typebot.com/api-reference/typebot/update
PATCH /v1/typebots/{typebotId}
# Create a workspace
Source: https://docs.typebot.com/api-reference/workspace/create
POST /v1/workspaces
# Delete a workspace
Source: https://docs.typebot.com/api-reference/workspace/delete
DELETE /v1/workspaces/{workspaceId}
# Get a workspace
Source: https://docs.typebot.com/api-reference/workspace/get
GET /v1/workspaces/{workspaceId}
# List workspaces
Source: https://docs.typebot.com/api-reference/workspace/list
GET /v1/workspaces
# List members
Source: https://docs.typebot.com/api-reference/workspace/list-members
GET /v1/workspaces/{workspaceId}/members
# Update a workspace
Source: https://docs.typebot.com/api-reference/workspace/update
PATCH /v1/workspaces/{workspaceId}
# Typebot Schema Releases
Source: https://docs.typebot.com/breaking-changes
## v6.1
* Introduces new defaults for web typebot theme to match the new Typebot branding.
## v6.0
* List variables now don't automatically display the last item when inserted into a bubble. It was too "magical". Now you can leverage the inline code feature to easily get the last element of a list:
```
{{={{List var}}.at(-1)=}}
```
Check out the new [Inline variable formatting section](./editor/variables) for more information.
* Input prefill is now disabled by default. You can still enable it in the [Settings](./settings/overview) tab of your bot.
* `Message sequence` option in the OpenAI block was removed because it was also too "magical" and it. Now I've introduced the `Dialogue` option. For more information:
# Guidelines
Source: https://docs.typebot.com/contribute/guidelines
## Code
* When introducing new i18n keys, only provide en.json translations. The rest will be [translated in Tolgee](./guides/translation) later on.
## Pull requests
* Before pushing any changes, we recommend you to build the project to make sure it's working as expected by running `bun run build` at the root of the repository.
* The PR title and description should simply describe what the PR is about. We don't follow any conventions.
* It's appreciated to add screenshots or videos of the changes when it's UI related
* No need to add any tags
* If your PR should close an issue when merged, add `Closes #` in the PR description.
* We prefer to push atomic commits without bothering about commit message conventions. All of them will be squashed before being merged, so it doesn't matter.
* Always let the author resolve himself the review threads he started
* Once you pushed changes after a review, make sure to [re-request a review](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review#requesting-reviews-from-collaborators-and-organization-members).
# Contribute to the blog
Source: https://docs.typebot.com/contribute/guides/blog
The [official Typebot blog](https://typebot.io/blog) is a place where we share any ideas, original content related to the chatbot industry, and Typebot itself.
You are free to contribute to the blog or fix any typos you may find.
1. Head over to the [content folder](https://github.com/baptisteArno/typebot.io/tree/main/apps/landing-page/app/features/blog/content) on the Github repo.
2. Click on the blog post file you want to edit. Or create a new file by clicking on the `Add file` button.
3. If you did not already have a fork of the repository, you will be prompted to create one.
4. Once you're happy with your changes, hit `Commit changes...`.
5. Click on `Create pull request`.
6. Add a title and a description to describe your changes.
7. Click on `Create pull request`.
It will be reviewed and merged if approved!
## New article guidelines
* The article should be related to chatbots, or Typebot.
* The article should be written in English.
* The article should be original content. No plagiarism.
* The article should not be 100% AI-generated.
The mdx file should always start with the following frontmatter:
```md theme={null}
---
title: 'My awesome blog post'
description: 'A short summary of the blog post.'
postedAt: '2023-11-19'
author: ''
---
```
If you are a new author, you need to add your information to the `apps/landing-page/app/features/blog/data` folder.
All images need to be placed under the `public/blog-assets/` folder where `` is the name of the mdx file you are creating/editing. The image file name should be in lowercase and separated by `-`.
All links to other blog posts should look like `./.mdx`.
Here are all the components you can use in your blog post:
* `Image`: To display an image. Make sure you define width and height prop to avoid content shifting. Example: ``.
Used to wrap the image in a frame and display a caption below it.
* `Info`: To display a callout block with an info icon. Example: `This is an info callout`.
* `Success`: To display a callout block with a success icon. Example: `This is a success callout`.
* `Warning`: To display a callout block with a warning icon. Example: `This is a warning callout`.
* `Typebot`: To embed a typebot as a Standard component. Example: ``. You can provide the same props as the [Standard component](../../deploy/web/react#standard).
* `YouTube`: To embed a YouTube video. Example: ``
* `Cta`: To display a call-to-action that redirects to Typebot.
Example:
```tsx theme={null}
// Displays a CTA with default text content
// Displays a minimalist CTA with just a logo and the CTA button
```
# Create a new block
Source: https://docs.typebot.com/contribute/guides/create-block
Creating a new block on Typebot is pretty easy and straightforward using our in-house framework [The Forge](../the-forge/overview).
If you are considering merging this new block to the official Typebot
repository, make sure to open a [Github
issue](https://github.com/baptisteArno/typebot.io/issues/new) first. This will
allow us to discuss the specification and the best way to implement it.
1. [Install the project locally](./local-installation)
2. Create a new branch:
```sh theme={null}
git checkout -b MY_BRANCH_NAME
```
3. Create your new block using the [Forge CLI](../the-forge/overview#forge-cli):
```sh theme={null}
bun create-new-block
```
4. The files should be generated in `packages/forge/blocks/YOUR_BLOCK_NAME`
5. Add the block's SVG logo in `packages/forge/blocks/YOUR_BLOCK_NAME/src/logo.tsx`
6. Right away you should be able to [run the application](./local-installation#running-the-project-locally) and see your newly-created logo in the sidebar of the editor.
7. Create a new action in the `packages/forge/blocks/YOUR_BLOCK_NAME/src/actions` folder. See [Action](../the-forge/action) for more information.
8. List this action in the `actions` array in `packages/forge/blocks/YOUR_BLOCK_NAME/src/index.ts`
9. Implement the action handler in `packages/forge/blocks/YOUR_BLOCK_NAME/src/handlers.ts`. See [Run](../the-forge/run) for more information.
10. To go further, check out the [Forge documentation](../the-forge/overview).
Make sure to check out other blocks implementations in the [packages/forge/blocks](https://github.com/baptisteArno/typebot.io/tree/main/packages/forge/blocks) folder.
## Video tutorials
Make sure to join our [Discord community](https://typebot.io/discord) to participate to these weekly office hours.
# Contribute to the documentation
Source: https://docs.typebot.com/contribute/guides/documentation
## For a quick fix
If the documentation is missing something, or you found a typo you can quickly edit the documentation:
1. Go to the documentation page you want to edit.
2. Click on the "Suggest edits" button at the bottom of the page.
3. You are redirected to a Github page where you can edit the content of the doc.
4. If you did not already have a fork of the repository, you will be prompted to create one.
5. Edit the content of the doc.
6. Hit "Commit changes...".
7. Click on "Create pull request".
8. Add a title and a description to describe your changes.
9. Click on "Create pull request".
It will be reviewed and merged if approved!
## For a bigger modification
If you'd like to add a new page or add a new section to the documentation:
1. [Install the project locally](./local-installation)
2. Create a new branch:
```sh theme={null}
git checkout -b MY_BRANCH_NAME
```
3. Run the docs in dev mode
```sh theme={null}
cd apps/docs
bun dev
```
4. All your docs modification will be displayed in real time.
5. Once you are done, commit your changes and push your branch.
6. Create a pull request on the [Github repository](https://github.com/baptisteArno/typebot.io).
It will be reviewed and merged if approved!
# Install the project locally
Source: https://docs.typebot.com/contribute/guides/local-installation
## Get started
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your
own GitHub account and then
[clone](https://help.github.com/articles/cloning-a-repository/) it to your local device.
## Running the project locally
1. Make sure you have node, [bun](https://bun.sh/docs/installation) and [docker](https://docs.docker.com/compose/install/) installed. For node, I suggest you use [`proto`](https://moonrepo.dev/proto) or [`nvm`](https://github.com/nvm-sh/nvm) allowing you to manage different versions. It should then autodetect which version need to be installed before running any command.
2. Install dependencies
```sh theme={null}
cd typebot.io
bun install
```
3. Set up environment variables
Copy `.env.dev.example` to `.env`
Check out the [Configuration guide](https://docs.typebot.io/self-hosting/configuration) if you want to enable more options
4. If you use the default DATABASE\_URL, you need a matching database running. You can do that easily with the provided `docker-compose.dev.yml` file:
```sh theme={null}
docker compose -f docker-compose.dev.yml up -d
```
This will also create a minio instance to enable file uploads.
5. Start the builder and viewer
```sh theme={null}
bun dev
```
Builder is available at [`http://localhost:3000`](http://localhost:3000)
Viewer is available at [`http://localhost:3001`](http://localhost:3001)
By default, you can easily authenticate in the builder using the "Github Sign In" button. For other options, check out the [Configuration guide](https://docs.typebot.io/self-hosting/configuration).
6. Optionnally you can also run the other available apps:
For the landing page:
```sh theme={null}
bunx nx dev landing-page
```
For the docs:
```sh theme={null}
bunx nx dev docs
```
# Translate
Source: https://docs.typebot.com/contribute/guides/translation
You speak a language other than English? You can help us translate the application! And it's easy! We use [Tolgee](https://tolgee.io/) to manage translations. It's a great tool that allows you to translate directly in the browser.
All you need to do is to join the [Discord server](https://discord.gg/xjyQczWAXV) and ask for an access to Tolgee in the [#contributors](https://discord.com/channels/1155799591220953138/1155883114455900190) channel.
You'll have a granted access and will be able to translate existing keys directly in the Tolgee platform:
# Contribute
Source: https://docs.typebot.com/contribute/overview
You are considering contributing to Typebot. I and the Fair Source community thank you for this 🙏.
Any contributions you make are **greatly appreciated**. There are many ways to contribute, from improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into Typebot itself.
If you are considering implementing a new feature or a bug fix, please open an
issue first. This will allow us to discuss the specficiation and the best way
to implement it.
Use the Forge. Our in-house framework to easily add new blocks on Typebot.
Help us have a gigantic library of third-party native integrations on Typebot.
Use our framework "The Forge" to easily implement a new block. Help us have a
gigantic library of third-party native integrations on Typebot.
Improve the documentation by fixing typos, adding missing information or
proposing new sections.
Write original content for Typebot's blog. Share your knowledge and ideas to a
wider audience. The author will be credited.
Report issues you encounter while using Typebot. This will help us improve the
product and make it even better.
Engaging with the community and helping others is a great way to contribute to
the project. We'd love to see you on our Discord server. ❤️
If you don't have time to contribute to the project. You can still show your
appreciation for the project and sponsor my work on Github.
# Action
Source: https://docs.typebot.com/contribute/the-forge/action
An action is what a block can do when it is executed with Typebot. A [block](./block) can have multiple actions.
Here is the `sendMessage` action definition:
```ts theme={null}
import { createAction, option } from "@typebot.io/forge";
import { auth } from "../auth";
export const sendMessage = createAction({
auth,
name: "Send message",
options: option.object({
chatId: option.string.meta({ layout: {
label: "Chat ID",
placeholder: "@username",
} }),
text: option.string.meta({ layout: {
label: "Message text",
input: "textarea",
} }),
}),
});
```
The action execution logic is defined separately in a `handlers.ts` file. See
the [Run](./run) documentation for more information.
## Props
The name of the action.
If the block requires authentication, the auth object needs to be passed to
the action.
If the block has options defined (see [block props](./block#props)), this
needs to be provided here.
The action configuration options. See Options for more
information.
If the action can stream content, this function should return the variable ID
that will receive the streamed content. See
Server function + stream for more
information.
If the action displays an embed bubble that waits for an event, this function
should return the variable ID where the event data will be saved. See
Display embed bubble for more
information.
A function that returns an array of variable IDs that will be set by this
action. This is used for analytics and tracking purposes.
An array of fetcher references used to populate dropdown options dynamically.
Each fetcher should be exported from the action file and implemented in the
handlers file. See Fetcher for more information.
An array of block IDs that this action can be converted into. This allows
users to easily switch between similar blocks while preserving their
configuration.
The action execution logic is now defined separately in a `handlers.ts` file
using `createActionHandler()` and `createFetcherHandler()`. Check out the
Run documentation for more information on how to implement
handlers.
# Auth
Source: https://docs.typebot.com/contribute/the-forge/auth
## Encrypted credentials
The authentication type.
The name of the credentials. I.e. `Twitter account`, `OpenAI account`, `Stripe
keys`, etc.
The schema of the data that needs to be stored. See [Options](./options) for
more information.
Example:
```ts theme={null}
option.object({
apiKey: option.string.meta({ layout: {
isRequired: true,
label: "API key",
withVariableButton: false,
} }),
});
```
## OAuth
The authentication type for OAuth 2.0 flow.
The name of the credentials. I.e. `Gmail account`, `Google Drive`, `GitHub
account`, etc.
The authorization URL for the OAuth provider where users will be redirected to
authenticate.
The token endpoint URL where the authorization code will be exchanged for
access tokens.
An array of OAuth scopes that define the permissions your application is
requesting.
An object defining the default environment variable names for the OAuth client
credentials.
The environment variable name for the OAuth client ID.
The environment variable name for the OAuth client secret.
Additional parameters to include in the authorization request.
Example:
```ts theme={null}
const gmailScopes = [
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.labels",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
] as const;
export const auth = createAuth({
type: "oauth",
name: "Gmail account",
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
tokenUrl: "https://oauth2.googleapis.com/token",
scopes: gmailScopes,
defaultClientEnvKeys: {
id: "GMAIL_CLIENT_ID",
secret: "GMAIL_CLIENT_SECRET",
},
extraAuthParams: {
access_type: "offline",
prompt: "consent",
},
});
```
# Block
Source: https://docs.typebot.com/contribute/the-forge/block
After using the [CLI](./cli) to create your new block. The `index.ts` file contains the block definition. It should look like:
## Props
The block ID. It should be unique all the other blocks.
A concise name for the block. Should be short enough to fit into a small block
card.
Logo used on the dark mode.
The full name that will be displayed as a tooltip when the mouse hovers the
block card.
List of strings describing the block. Used for block searching.
See Auth for more information.
A list of all the possible actions that this block provides. See
Action for more information
The dedicated documentation URL. (i.e.
`https://docs.typebot.io/editor/blocks/integrations/openai`)
Provide it if all the block actions share the same properties. See
Options for more information. In the block settings it
will then be displayed between the auth and the actions:
A list of fetchers used in the provided options. See
Fetcher for more information.
# CLI
Source: https://docs.typebot.com/contribute/the-forge/cli
The CLI allows you to bootstrap a new block, creating all the necessary files and folders to get started.
It asks you a few questions about your block, and then creates the files and folders for you.
# Fetcher
Source: https://docs.typebot.com/contribute/the-forge/fetcher
Your action can have a `fetchers` property that is an array of fetcher references. Fetchers allow you to populate dropdown options dynamically by fetching data from external APIs.
## Define the fetcher in your action
First, export a fetcher constant and reference it in your action:
**In the action file** (`actions/createChatCompletion.ts`):
```ts theme={null}
import { createAction } from "@typebot.io/forge";
import { auth } from "../auth";
// Export the fetcher constant
export const modelsFetcher = {
id: "fetchModels",
} as const;
export const createChatCompletion = createAction({
name: "Create chat completion",
auth,
options: option.object({
model: option.string.meta({ layout: {
fetcher: modelsFetcher.id, // Reference the fetcher by its id
label: "Model",
placeholder: "Select a model",
} }),
// ... other options
}),
fetchers: [modelsFetcher], // Register the fetcher
// ...
});
```
## Implement the fetcher handler
The fetcher implementation logic should be defined in your handlers file using `createFetcherHandler`:
**In the handlers file** (`handlers.ts`):
```ts theme={null}
import { createActionHandler, createFetcherHandler } from "@typebot.io/forge";
import { parseUnknownError } from "@typebot.io/lib/parseUnknownError";
import { ky } from "@typebot.io/lib/ky";
import {
createChatCompletion,
modelsFetcher,
} from "./actions/createChatCompletion";
export default [
createActionHandler(createChatCompletion, {
server: async ({ credentials, options, variables, logs }) => {
// Action implementation
},
}),
createFetcherHandler(
createChatCompletion, // Pass the action as first parameter
modelsFetcher.id, // Pass the fetcher id
async ({ credentials, options }) => {
if (!credentials?.apiKey)
return {
data: [],
};
try {
const response = await ky
.get("https://api.example.com/models", {
headers: {
authorization: `Bearer ${credentials.apiKey}`,
},
})
.json<{ data: { id: string; name: string }[] }>();
return {
data: response.data.map((model) => ({
value: model.id,
label: model.name,
})),
};
} catch (err) {
return {
error: await parseUnknownError({ err }),
};
}
}
),
];
```
## Fetcher response format
The fetcher function must return an object with either a `data` or `error` property:
* **Success**: `{ data: (string | { label: string; value: string })[] }`
* **Error**: `{ error: string | { description: string; details?: string; context?: string } }`
The `data` array can contain either:
* Simple strings: `["model-1", "model-2", "model-3"]`
* Objects with `label` and `value`: `[{ label: "GPT-4", value: "gpt-4" }, { label: "GPT-3.5", value: "gpt-3.5-turbo" }]`
## Available parameters
The fetcher handler receives the following parameters:
* `credentials`: The authenticated credentials for the action
* `options`: The current values of all action options (useful when you have dependencies between options)
By passing the action as the first parameter to `createFetcherHandler`, TypeScript will automatically infer the correct types for `credentials` and `options`.
# Options
Source: https://docs.typebot.com/contribute/the-forge/options
The Forge library extends the [Zod](https://github.com/colinhacks/zod) library. This means that you can use any Zod schema to validate the data that you want to store for your block. The Forge stores layout metadata on schemas using Zod's `meta()` API so the Typebot editor can render the right inputs.
Options extends the `z.ZodObject` schema.
The Forge provide convenient functions to create the options schema for you. Even though you could provide straight Zod schemas, we highly recommend using `option` functions to create the options schema.
Here is an example of how a schema can be created using the `option` helpers and `meta()`:
```ts theme={null}
option.object({
token: option.string.meta({ layout: {
label: 'Token',
isRequired: true,
placeholder: 'Type your token...',
helperText: 'You can find your token [here](https://).',
} }),
role: option.enum(['user', 'admin']).meta({ layout: {
defaultValue: 'user',
label: 'Role',
} }),
phoneNumber: option.string.meta({ layout: {
accordion: 'Advanced settings',
label: 'Phone number',
placeholder: 'Type your phone number...',
} }),
address: option.string.meta({ layout: {
accordion: 'Advanced settings',
label: 'Address',
placeholder: 'Type your address...',
} }),
isTestModeEnabled: option.boolean.meta({ layout: {
label: 'Test mode',
defaultValue: true,
helperText: 'Enable test mode to use a test account.',
} }),
})
```
## Object
```ts theme={null}
option.object({
//...
})
```
## String
Example:
```ts theme={null}
option.string.meta({ layout: {
label: 'Name',
placeholder: 'Type a name...',
withVariableButton: false,
} })
```
## Number
Example:
```ts theme={null}
option.number.meta({ layout: {
label: 'Temperature',
defaultValue: 1,
direction: 'row',
} })
```
## Boolean
```ts theme={null}
option.boolean.meta({ layout: {
label: 'Test mode',
moreInfoTooltip: 'Enable test mode to use a test account.',
} })
```
## Enum
Example:
```ts theme={null}
option.enum(['user', 'admin']).meta({ layout: {
label: 'Role',
defaultValue: 'user',
} })
```
## Discriminated unions
Example:
```ts theme={null}
option.discriminatedUnion('type', [
option.object({
type: option.literal('user'),
name: option.string.meta({ layout: { placeholder: 'Type a name...' } }),
}),
option.object({
type: option.literal('admin'),
name: option.string.meta({ layout: { placeholder: 'Type a name...' } }),
phoneNumber: option.string.meta({ layout: {
placeholder: 'Type a phone number...',
} }),
}),
])
```
## Literal
Used mainly for [discriminated unions](./options#discriminated-unions). It is not visible on the Typebot editor.
Example:
```ts theme={null}
option.literal('user')
```
## Array
Use this to collect a list of values.
Example:
* A list of names
```ts theme={null}
option.array(option.string.meta({ layout: { placeholder: 'Type a name...' } })).meta({ layout: {
label: 'Names',
itemLabel: 'name',
} })
```
## Helpers
### Save Response Array
Use this to save the response of an array of options in variables.
For example if you want your user to be able to save the response of an HTTP request to variables:
```ts theme={null}
option.saveResponseArray(['Message content', 'Total tokens']).meta({ layout: {
accordion: 'Save response',
} })
```
You provide the list of all the possible response values to save.
## Layout props
The label of the option. Will often be displayed right above the input.
The placeholder of the input.
The helper text of the input. Will often be displayed below the input.
The name of the accordion where the option will be displayed in. For example if you'd like to group 2 properties in the same accordion named "Advanced settings", you can write:
```ts theme={null}
option.object({
temperature: option.number.meta({ layout: {
accordion: 'Advanced settings',
} }),
humidity: option.number.meta({ layout: {
accordion: 'Advanced settings',
} }),
})
```
The direction of the input. If set to `row`, the label will be displayed on
the left of the input.
The default value of the input.
The tooltip that will be displayed when the user hovers the info icon of the
input.
Whether or not to display the variable button next to the input.
The type of the input to display.
Whether or not the input is required. Will display a red star next to the
label if set to `true`.
Set this if you'd like your input to provide a dropdown of dynamically fetched items.
```ts theme={null}
option.string.meta({ layout: {
fetcher: 'fetchModels',
} })
```
`fetchModels` should match the `id` of the fetcher that you defined in the
`fetchers` prop of the action. See [Fetcher](./fetcher) for more information.
### Array only
The label of the items of an array option. Will be displayed next to the "Add"
label of the add button.
Whether or not the order of the items in an array schema matters. Will display
"plus" buttons above and below when hovering on an item.
# Overview
Source: https://docs.typebot.com/contribute/the-forge/overview
The Forge is a framework built by Typebot, for Typebot. It allows you to easily implement a new block.
This section goes through the different concepts of this framework and how to use it.
# Run
Source: https://docs.typebot.com/contribute/the-forge/run
Action execution logic is defined in a separate `handlers.ts` file using the `createActionHandler()` and `createFetcherHandler()` functions. This separates the action definition (schema, options) from its runtime implementation.
An action handler can do one of the following things:
* Execute a function on the server (most common)
* If block is followed by a streamable variable, stream the variable on the client. Otherwise, execute a function on the server.
* Execute a function on the client
* Display a custom embed bubble
## Handlers file structure
All handlers for a block should be defined in `src/handlers.ts` and exported as a default array:
```ts theme={null}
import { createActionHandler, createFetcherHandler } from "@typebot.io/forge";
import { sendMessage, modelsFetcher } from "./actions/sendMessage";
import { getMessage } from "./actions/getMessage";
export default [
createActionHandler(sendMessage, {
server: async ({ credentials, options, variables, logs }) => {
// Implementation for sendMessage
},
}),
createFetcherHandler(
sendMessage,
modelsFetcher.id,
async ({ credentials, options }) => {
// Implementation for fetcher
return {
data: ["model-1", "model-2"],
};
}
),
createActionHandler(getMessage, {
server: async ({ credentials, options, variables, logs }) => {
// Implementation for getMessage
},
}),
];
```
The handlers array can contain two types of handlers:
* **Action handlers** using `createActionHandler(action, implementation)` - Execute the action logic
* **Fetcher handlers** using `createFetcherHandler(action, fetcherId, implementation)` - Populate dropdown options dynamically (see [Fetcher](./fetcher) for more details)
## Server function
The most common handler is to execute a function on the server.
Example:
```ts theme={null}
import { createActionHandler } from "@typebot.io/forge";
import { sendMessage } from "./actions/sendMessage";
import { ky } from "@typebot.io/lib/ky";
export default [
createActionHandler(sendMessage, {
server: async ({
credentials: { apiKey },
options: { botId, message, responseMapping, threadId },
variables,
logs,
}) => {
const res: ChatNodeResponse = await ky
.post(apiBaseUrl + botId, {
headers: {
Authorization: `Bearer ${apiKey}`,
},
json: {
message,
chat_session_id: isEmpty(threadId) ? undefined : threadId,
},
})
.json();
if (res.error)
logs.add({
status: "error",
description: res.error,
});
responseMapping?.forEach((mapping) => {
if (!mapping.variableId) return;
const item = mapping.item ?? "Message";
if (item === "Message") variables.set(mapping.variableId, res.message);
if (item === "Thread ID")
variables.set(mapping.variableId, res.chat_session_id);
});
},
}),
];
```
As you can see, the server function takes `credentials`, `options`, `variables` and `logs` as arguments.
The `credentials` are the credentials that the user has entered in the credentials block.
The `options` are the options that the user has entered in the options block.
The `variables` object contains helpers to save and get variables if necessary.
The `logs` allows you to log anything during the function execution. These logs will be displayed as toast in the preview mode or in the Results tab on production.
## Server function + stream
If your block can stream a message (like OpenAI), you need to define `getStreamVariableId` in the action and implement a stream handler.
**In the action definition** (`actions/createChatCompletion.ts`):
```ts theme={null}
import { createAction, option } from "@typebot.io/forge";
import { auth } from "../auth";
export const createChatCompletion = createAction({
auth,
name: "Create chat completion",
options: option.object({
// ... options
}),
getStreamVariableId: (options) =>
options.responseMapping?.find(
(res) => res.item === "Message content" || !res.item
)?.variableId,
});
```
**In the handlers file** (`handlers.ts`):
```ts theme={null}
import { createActionHandler } from "@typebot.io/forge";
import { createChatCompletion } from "./actions/createChatCompletion";
import { OpenAI } from "openai";
import { OpenAIStream } from "@typebot.io/ai";
export default [
createActionHandler(createChatCompletion, {
server: async (params) => {
// Server implementation when streaming is not available
},
stream: {
run: async ({ credentials: { apiKey }, options, variables }) => {
const config = {
apiKey,
baseURL: options.baseUrl,
defaultHeaders: {
"api-key": apiKey,
},
defaultQuery: options.apiVersion
? {
"api-version": options.apiVersion,
}
: undefined,
} satisfies ClientOptions;
const openai = new OpenAI(config);
const response = await openai.chat.completions.create({
model: options.model ?? defaultOpenAIOptions.model,
temperature: options.temperature
? Number(options.temperature)
: undefined,
stream: true,
messages: parseChatCompletionMessages({ options, variables }),
});
return { stream: OpenAIStream(response) };
},
},
}),
];
```
The `getStreamVariableId` function in the action definition determines which variable should be streamed.
The stream `run` function needs to return `Promise<{ stream?: ReadableStream, error?: { description: string, details?: string, context?: string } }>`.
## Client function
If you want to execute a function on the client instead of the server, you can use the `web` object in your handler.
This makes your block only compatible with the Web runtime. It won't work on
WhatsApp for example, the block will simply be skipped.
Example:
```ts theme={null}
import { createActionHandler } from "@typebot.io/forge";
import { shoutName } from "./actions/shoutName";
export default [
createActionHandler(shoutName, {
web: {
parseFunction: ({ options }) => {
return {
args: {
name: options.name ?? null,
},
content: `alert('Hello ' + name)`,
};
},
},
}),
];
```
The web function needs to return an object with `args` and `content`.
`args` is an object with arguments that are passed to the `content` context. Note that the arguments can't be `undefined`. If you want to pass a not defined argument, you need to pass `null` instead.
`content` is the code that will be executed on the client. It can call the arguments passed in `args`.
## Display embed bubble
If you want to display a custom embed bubble, you need to define `getEmbedSaveVariableId` in the action (if you want to save event data) and implement the display embed bubble handler. See [Cal.com
block](https://github.com/baptisteArno/typebot.io/blob/main/packages/forge/blocks/calCom) as an example.
**In the action definition** (`actions/bookEvent.ts`):
```ts theme={null}
import { createAction, option } from "@typebot.io/forge";
import { auth } from "../auth";
export const bookEvent = createAction({
auth,
name: "Book event",
options: option.object({
// ... options
saveResultInVariableId: option.string.meta({ layout: {
inputType: "variableDropdown",
} }),
}),
getEmbedSaveVariableId: (options) => options.saveResultInVariableId,
});
```
**In the handlers file** (`handlers.ts`):
```ts theme={null}
import { createActionHandler } from "@typebot.io/forge";
import { bookEvent } from "./actions/bookEvent";
export default [
createActionHandler(bookEvent, {
web: {
displayEmbedBubble: {
parseUrl: ({ options }) => options.url,
parseInitFunction: ({ options }) => ({
args: {
cal: options.cal,
},
content: `// Initialize embed with typebotElement`,
}),
waitForEvent: {
parseFunction: () => ({
args: {},
content: `// Handle event with continueFlow()`,
}),
},
},
},
}),
];
```
The `getEmbedSaveVariableId` function in the action definition determines which variable will store the event data.
The `displayEmbedBubble` object in the handler requires:
* `parseUrl`: Returns a URL to be displayed as a text bubble in runtimes where the code can't be executed (e.g., WhatsApp)
* `parseInitFunction`: Returns a function to execute on initialization. The function content can use the `typebotElement` variable to get the DOM element where the block is rendered.
* `waitForEvent.parseFunction` (optional): Returns a function to handle the event. The function content can use the `continueFlow` function to continue the flow with the event data.
# API
Source: https://docs.typebot.com/deploy/api/overview
Your bot can also be executed with HTTP requests. This is useful if you want to integrate your bot with another service or if you want to use it in a different programming language.
## Test
1. All your requests need to be authenticated with an API token. [See instructions](/api-reference/authentication).
2. To start the chat, send a POST request to `https://typebot.io/api/v1/typebots//preview/startChat` The first response will contain a sessionId that you will need for subsequent requests.
3. To send replies, send POST requests to `https://typebot.io/api/v1/sessions//continueChat`
With the following JSON body:
```json theme={null}
{
"message": "This is my reply"
}
```
Check out the [Start preview chat API reference](/api-reference/chat/start-preview-chat) for more information
## Live
1. To start the chat, send a POST request to `https://typebot.io/api/v1/typebots//startChat` The first response will contain a sessionId that you will need for subsequent requests.
2. To send replies, send POST requests to `https://typebot.io/api/v1/sessions//continueChat`
With the following JSON body:
```json theme={null}
{
"message": "This is my reply"
}
```
Check out the [Start chat API reference](/api-reference/chat/start-chat) for more information
# Blink
Source: https://docs.typebot.com/deploy/web/blink
Head over to the Share tab of your bot and click on the Blink button to get the embed instructions specific to your bot.
1. In the Blink Admin window, head over to `Content Studio > Hub`.
2. Click on the `Add Content > Form` button.
3. For the form provider, select `Other`.
4. Paste your bot URL and customize the look and feel of this new form.
5. You can optionally add Custom Variables meaning that you can [prefill the variables](/editor/variables#prefilled-variables) in your bot with the respondant's Blink data. For example you can prefill the `Name` bot variable with the `First Name` Blink variable.
# Add a custom domain
Source: https://docs.typebot.com/deploy/web/custom-domain
Custom domains are available on the **Pro plan** and above. If you are on Free or Starter, the option will not appear in the Share tab. See the [pricing page](https://typebot.com/pricing) for details.
You can bind a custom domain to your typebot in the "Share" tab.
To connect a new domain, follow the instructions:
Once you've added the corresponding DNS record, click on the "Save" button. You might have to wait for a few minutes before the record is properly propagated.
## Troobleshooting
If your domain is not properly configured or verified, you will see this error icon next to your domain link:
Make sure to click on it to see what is required to do to fix the issue.
# HTML & Javascript
Source: https://docs.typebot.com/deploy/web/html-javascript
## Standard
You can get the standard HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
There, you can change the container dimensions. Here is a code example:
```html theme={null}
```
This code is creating a container with a 100% width (will match parent width) and 600px height.
```ts theme={null}
type BotProps = {
id?: string;
typebot: string | any;
isPreview?: boolean;
resultId?: string;
prefilledVariables?: Record;
apiHost?: string;
wsHost?: string;
font?:
| string
| {
type: "Google";
family?: string | undefined;
}
| {
type: "Custom";
url?: string | undefined;
family?: string | undefined;
css?: string | undefined;
};
progressBarRef?: HTMLDivElement;
startFrom?:
| {
type: "group";
groupId: string;
}
| {
type: "event";
eventId: string;
};
sessionId?: string;
theme?: {
chatWindow?: {
backgroundColor?: string;
maxWidth?: string;
maxHeight?: string;
};
button?: {
size?: "medium" | "large" | `${number}px`;
backgroundColor?: string;
iconColor?: string;
customIconSrc?: string;
customCloseIconSrc?: string;
};
previewMessage?: {
backgroundColor?: string;
textColor?: string;
closeButtonBackgroundColor?: string;
closeButtonIconColor?: string;
};
position?: "fixed" | "static"; // Defaults to "fixed"
placement?: "left" | "right"; // Defaults to "right"
};
previewMessage?: {
avatarUrl?: string;
message: string;
autoShowDelay?: number;
};
autoShowDelay?: number;
onNewInputBlock?: (inputBlock: any) => void;
onAnswer?: (answer: { message: string; blockId: string }) => void;
onInit?: () => void;
onEnd?: () => void;
onNewLogs?: (
logs: {
status: string;
description: string;
details?: unknown;
}[]
) => void;
onChatStatePersisted?: (isEnabled: boolean) => void;
onScriptExecutionSuccess?: (message: string) => void;
};
```
### Multiple bots
If you have different bots on the same page you will have to make them distinct with an additional `id` prop:
```html theme={null}
...
```
## Popup
You can get the popup HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
Here is an example:
```html theme={null}
```
This code will automatically trigger the popup window after 3 seconds.
```ts theme={null}
type PopupProps = {
id?: string;
typebot: string | any;
isPreview?: boolean;
resultId?: string;
prefilledVariables?: Record;
apiHost?: string;
wsHost?: string;
font?:
| string
| {
type: "Google";
family?: string | undefined;
}
| {
type: "Custom";
url?: string | undefined;
family?: string | undefined;
css?: string | undefined;
};
progressBarRef?: HTMLDivElement;
startFrom?:
| {
type: "group";
groupId: string;
}
| {
type: "event";
eventId: string;
};
sessionId?: string;
theme?: {
chatWindow?: {
backgroundColor?: string;
maxWidth?: string;
maxHeight?: string;
};
button?: {
size?: "medium" | "large" | `${number}px`;
backgroundColor?: string;
iconColor?: string;
customIconSrc?: string;
customCloseIconSrc?: string;
};
previewMessage?: {
backgroundColor?: string;
textColor?: string;
closeButtonBackgroundColor?: string;
closeButtonIconColor?: string;
};
placement?: "left" | "right";
};
previewMessage?: {
avatarUrl?: string;
message: string;
autoShowDelay?: number;
};
autoShowDelay?: number;
onNewInputBlock?: (inputBlock: any) => void;
onAnswer?: (answer: { message: string; blockId: string }) => void;
onInit?: () => void;
onEnd?: () => void;
onNewLogs?: (
logs: {
status: string;
description: string;
details?: unknown;
}[]
) => void;
onChatStatePersisted?: (
isEnabled: boolean,
{ typebotId }: { typebotId: string }
) => void;
onScriptExecutionSuccess?: (message: string) => void;
autoShowDelay?: number;
theme?: {
width?: string;
backgroundColor?: string;
zIndex?: number;
};
defaultOpen?: boolean;
isOpen?: boolean;
onOpen?: () => void;
onClose?: () => void;
};
```
## Bubble
You can get the bubble HTML and Javascript code by clicking on the "HTML & Javascript" button in the "Share" tab of your typebot.
Here is an example:
```html theme={null}
```
This code will show the bubble and let a preview message appear after 5 seconds.
```ts theme={null}
type BubbleProps = {
id?: string;
typebot: string | any;
isPreview?: boolean;
resultId?: string;
prefilledVariables?: Record;
apiHost?: string;
wsHost?: string;
font?:
| string
| {
type: "Google";
family?: string | undefined;
}
| {
type: "Custom";
url?: string | undefined;
family?: string | undefined;
css?: string | undefined;
};
progressBarRef?: HTMLDivElement;
startFrom?:
| {
type: "group";
groupId: string;
}
| {
type: "event";
eventId: string;
};
sessionId?: string;
theme?: {
chatWindow?: {
backgroundColor?: string;
maxWidth?: string;
maxHeight?: string;
};
button?: {
isHidden?: boolean;
size?: "medium" | "large" | `${number}px`;
backgroundColor?: string;
iconColor?: string;
customIconSrc?: string;
customCloseIconSrc?: string;
};
previewMessage?: {
backgroundColor?: string;
textColor?: string;
closeButtonBackgroundColor?: string;
closeButtonIconColor?: string;
};
placement?: "left" | "right";
};
previewMessage?: {
avatarUrl?: string;
message: string;
autoShowDelay?: number;
};
autoShowDelay?: number;
isOpen?: boolean;
onNewInputBlock?: (inputBlock: any) => void;
onAnswer?: (answer: { message: string; blockId: string }) => void;
onInit?: () => void;
onEnd?: () => void;
onNewLogs?: (
logs: {
status: string;
description: string;
details?: unknown;
}[]
) => void;
onChatStatePersisted?: (isEnabled: boolean) => void;
onScriptExecutionSuccess?: (message: string) => void;
onOpen?: () => void;
onClose?: () => void;
onPreviewMessageClick?: () => void;
onPreviewMessageDismissed?: () => void;
};
```
### Custom button position
You can move the button with some custom CSS on your website. For example, you can place the bubble button higher with the following CSS:
```css theme={null}
typebot-bubble::part(button) {
bottom: 60px;
}
typebot-bubble::part(bot) {
bottom: 140px;
height: calc(100% - 140px)
}
```
If you have a preview message, you'll also have to manually position it:
```css theme={null}
typebot-bubble::part(preview-message) {
bottom: 140px;
}
```
### Hide preview message after interaction
You can hide the preview message after the user has interacted with the bot. For example, this code will show the preview message only until the user has either launched the bot or dismissed the preview message:
```js theme={null}
Typebot.initBubble({
typebot: "my-typebot",
previewMessage: localStorage.getItem("hideBotPreviewMessage")
? undefined
: { message: "I have a question for you!" },
onPreviewMessageDismissed: () => {
localStorage.setItem("hideBotPreviewMessage", "true");
},
onInit: () => {
localStorage.setItem("hideBotPreviewMessage", "false");
},
});
```
This uses the `localStorage` API to remember the state of the preview message.
## Commands
Here are the commands you can use to trigger your embedded typebot:
* `Typebot.open()`: Open popup or bubble
* `Typebot.close()`: Close popup or bubble
* `Typebot.toggle()`: Toggle the bubble or popup open/close state,
* `Typebot.showPreviewMessage()`: Show preview message from the bubble,
* `Typebot.hidePreviewMessage()`: Hide preview message from the bubble,
* `Typebot.reset()`: Resets remembered state of the bot (only useful if `Remember user` is enabled),
* `Typebot.setPrefilledVariables(...)`: Set prefilled variables.
Example:
```js theme={null}
Typebot.setPrefilledVariables({
Name: "Jhon",
Email: "john@gmail.com",
});
```
For more information, check out [Additional configuration](#additional-configuration).
* `Typebot.setInputValue(...)`: Set the value in the currently displayed input.
* `Typebot.submitInput()`: Submit the currently displayed input.
* `Typebot.sendCommand(...)`: Send a [command](/editor/events/command) to the bot.
* `Typebot.reload()`: Reload the bot.
You can bind these commands on a button element, for example:
```html theme={null}
```
For each command you can pass an optional `id` prop to target a specific typebot. I.e. `Typebot.open({ id: 'my-bubble' })`
## Callbacks
If you need to trigger events on your parent website when the user interact with the bot, you can use the following callbacks:
```js theme={null}
Typebot.initStandard({
typebot: "my-typebot",
onNewInputBlock: (inputBlock) => {
console.log("New input block displayed", inputBlock.id);
},
onAnswer: (answer) => {
console.log("Answer received", answer.message, answer.blockId);
},
onInit: () => {
console.log("Bot initialized");
},
onEnd: () => {
console.log("Bot ended");
},
});
```
## Additional configuration
You can prefill the bot variable values in your embed code by adding the `prefilledVariables` option. Here is an example:
```js theme={null}
Typebot.initStandard({
typebot: "my-typebot",
prefilledVariables: {
"Current URL": "https://my-site/account",
"User name": "John Doe",
},
});
```
It will prefill the `Current URL` variable with "[https://my-site/account](https://my-site/account)" and the `User name` variable with "John Doe". More info about variables: [here](/editor/variables).
Note that if your site URL contains query params (i.e. [https://typebot.io?User%20name=John%20Doe](https://typebot.io?User%20name=John%20Doe)), the variables will automatically be injected to the typebot. So you don't need to manually transfer query params to the bot embed configuration.
# Iframe
Source: https://docs.typebot.com/deploy/web/iframe
You can easily get your typebot iframe code by clicking on the "Iframe" button in the "Share" tab of your typebot.
Here, you can set up its width and height. A good default is a `width` of `100%` and a `height` of `600px`.
# Next.js
Source: https://docs.typebot.com/deploy/web/next-js
## Install
```bash theme={null}
npm install @typebot.io/react
```
## Standard
```tsx theme={null}
import { Standard } from '@typebot.io/react'
const App = () => {
return (
)
}
```
This code is creating a container with a 100% width (will match parent width) and 600px height.
## Popup
```tsx theme={null}
import { Popup } from '@typebot.io/react'
const App = () => {
return
}
```
This code will automatically trigger the popup window after 3 seconds.
## Bubble
```tsx theme={null}
import { Bubble } from '@typebot.io/react'
const App = () => {
return (
)
}
```
This code will show the bubble and let a preview message appear after 5 seconds.
## Additional configuration
You can prefill the bot variable values in your embed code by adding the `prefilledVariables` option. Here is an example:
```tsx theme={null}
import { Standard } from '@typebot.io/react'
const App = () => {
return (
)
}
```
It will prefill the `Current URL` variable with "[https://my-site/account](https://my-site/account)" and the `User name` variable with "John Doe". More info about variables: [here](/editor/variables).
Note that if your site URL contains query params (i.e. [https://typebot.io?User%20name=John%20Doe](https://typebot.io?User%20name=John%20Doe)), the variables will automatically be injected to the typebot. So you don't need to manually transfer query params to the bot embed configuration.
# Overview
Source: https://docs.typebot.com/deploy/web/overview
To get the appropriate instructions to deploy your typebot in your platform of choice, make sure to head over the `Share` tab of your bot and select the platform you want to deploy your typebot on.
You can choose to embed your typebot in 3 different ways.
## Standard
Embeds the typebot in a box with the size of your choice anywhere on your app. This is what is used on Typebot homepage:
You can also set the width to `100%` and the height to `100vh` to make it take the entire page dimensions
## Popup
Embeds the typebot in a Popup that overlays your website. It can be triggered after a delay or with a click of a button for example
## Bubble
Embeds the typebot as a "chat bubble" at the bottom right corner of your site. Can be triggered automatically or with a click. It can also come with a "proactive message".
# React
Source: https://docs.typebot.com/deploy/web/react
## Install
```bash theme={null}
npm install @typebot.io/react
```
## Standard
```tsx theme={null}
import { Standard } from '@typebot.io/react'
const App = () => {
return (
)
}
```
This code is creating a container with a 100% width (will match parent width) and 600px height.
## Popup
```tsx theme={null}
import { Popup } from '@typebot.io/react'
const App = () => {
return
}
```
This code will automatically trigger the popup window after 3 seconds.
## Bubble
```tsx theme={null}
import { Bubble } from '@typebot.io/react'
const App = () => {
return (
)
}
```
This code will show the bubble and let a preview message appear after 5 seconds.
## Additional configuration
You can prefill the bot variable values in your embed code by adding the `prefilledVariables` option. Here is an example:
```tsx theme={null}
import { Standard } from '@typebot.io/react'
const App = () => {
return (
)
}
```
It will prefill the `Current URL` variable with "[https://my-site/account](https://my-site/account)" and the `User name` variable with "John Doe". More info about variables: [here](/editor/variables).
Note that if your site URL contains query params (i.e. [https://typebot.io?User%20name=John%20Doe](https://typebot.io?User%20name=John%20Doe)), the variables will automatically be injected to the typebot. So you don't need to manually transfer query params to the bot embed configuration.
# Script embed snippet
Source: https://docs.typebot.com/deploy/web/script
The script embed option is useful only if you don't have access to the HTML tree of your application or if your website builder only allows you to inline script snippets.
Otherwise, it's preferable to follow [HTML & Javascript](./html-javascript) embed instructions because the script snippets are just scripts that will inject the code from the HTML & Javascript embed method.
# Webflow
Source: https://docs.typebot.com/deploy/web/webflow
Head over to the Share tab of your bot and click on the Webflow button to get the embed instructions of your bot.
## Advanced guides
### Trigger a typebot command on a click of a button
1. Head over to the `Settings` tab of your button and add a dedicated `ID`
2. In your typebot `Embed` element, insert this code in the existing `
```
Make sure to replace `BUTTON_ID_1` and `BUTTON_ID_2` with the ID you added on your button elements.
In this example we are opening the popup when the specified buttons are clicked but you could also use any of the [available commands](./html-javascript#commands).
# WordPress
Source: https://docs.typebot.com/deploy/web/wordpress
Typebot has a native [WordPress plug-in](https://wordpress.org/plugins/typebot/) that helps you embed typebots in your WordPress site.
Of course, before using it, you need to create and publish your first typebot.
The code snippet to paste is easily configurable in the Share tab of your bot after clicking on the "Wordpress" button.
## Excluded pages
The excluded pages input is a comma-separated list of pages where you don't want your typebot to appear.
Examples:
* `/app/*` will exclude all pages starting with `/app/`
* `/app` will only exclude the `/app` page
* `/app?param=1` will only exclude the `/app` page **and** with the `param` query parameter set to `1`
* `/app?param=*` will exclude the page at `/app` **and** with the `param` query parameter set to anything
* `/app/*?param=*` will exclude all pages starting with `/app/` **and** with the `param` query parameter set to anything
## Personalize user experience
You can leverage the [prefilled variables](../../editor/variables#prefilled-variables) and inject your user information directly into your typebot so that the experience is entirely customized to your user.
Here are the available variables from WordPress, make sure to create them in your typebot's variables dropdown:
The only thing you need to do to enable this is:
* Use the [Wordpress Typebot plugin](https://wordpress.com/plugins/typebot)
* Have the variables declared in your Typebot with the exact syntaxes. For the email for example, make sure your variable is spelled `WP Email`. These won't work: `wp Email`, `WP email`.
## Your typebot isn't showing?
### You have litespeed with "Localise Resources" enabled
There is an a box where there is a list of URLs it localises, one of them was ‘[https://cdn.jsdelivr.net’](https://cdn.jsdelivr.net’). This URL should be removed from it since it is used to import the embed library.
## You have litespeed with cache enabled
Make sure to insert `web.js` and `typebot` in the JS Excludes textbox and JS Deferred Excludes under Tuning Settings.
### You have a cache plugin
Plugins like WP Rocket prevent Typebot to work.
For WP Rocket:
1. Go to Settings > WP Rocket > Excluded Inline Javascript:
2. Type "typebot"
3. Save
### You have plugin that adds `defer` attribute to external scripts
You need to add an exception for Typebot in the corresponding plugin config.
### Still not working
Contact me on the application using the typebot at the bottom right corner
# Create a WhatsApp Meta app
Source: https://docs.typebot.com/deploy/whatsapp/create-meta-app
## 1. Create a Facebook Business account
1. Head over to [https://business.facebook.com](https://business.facebook.com) and log in
2. Create a new business account on the left side bar
It is possible that Meta automatically restricts your newly created Business
account. In that case, make sure to verify your identity to proceed.
## 2. Create a Meta app
1. Head over to [https://developers.facebook.com/apps](https://developers.facebook.com/apps)
2. Click on Create App
3. "What do you want your app to do?", select `Other`.
4. Select `Business` type
5. Give it any name and select your newly created Business Account
6. On the app page, look for `WhatsApp` product and enable it
You can then follow the instructions in the Share tab of your bot to connect your Meta app to Typebot.
# WhatsApp
Source: https://docs.typebot.com/deploy/whatsapp/overview
## Test
You can preview and test your bot by clicking on the `Test` button in the editor and change the runtime to `WhatsApp`.
### Troubleshooting
This can be due to a mismatch between the WhatsApp number displayed in your WhatsApp application profile settings and the number you have typed in Typebot.
For example, some Brazilians have 2 numbers, 1 with 8 digits, the other with 9 digits. In Typebot, you need to type the number that is displayed in your WhatsApp application profile settings to make sure the bot works properly.
If you don't receive the preview initial message, it means that the phone number you are using is not valid or not accepted by WhatsApp.
* Make sure you can actually send a message to Typebot's business phone number (+33 7 56 95 36 64).
* Make sure that you have accepted WhatsApp's latest Terms of Service.
* Make sure you have the latest version of WhatsApp installed on your phone.
* Make sure to type the number that is displayed in your WhatsApp application profile settings to make sure you receive the preview initial message.
## Limitations
WhatsApp environment have some limitations that you need to keep in mind when building the bot:
* GIF and SVG image files are not supported. They won't be displayed.
* Only .mp4 videos are supported (See [Supported Media Types](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types) for more info).
* WhatsApp only allows to display 3 buttons at a time. So we work around that by adding "..." messages to display more buttons.
* Cards input block can only display 3 buttons per card at a time.
* Buttons content can't be longer than 20 characters. If the content is longer, it will be truncated.
* Incompatible blocks, if present, they will be skipped:
* Payment input block
* Chatwoot block
* Script or Set Variable block with `Execute on client` option enabled
* Google Analytics block
* Meta Pixel blocks
* Cal.com block
## Contact information
You can automatically assign contact name and phone number to a variable in your bot using a Set variable block with the dedicated system values:
## Deploy on your phone number
Head over to the Share tab of your bot and click on the WhatsApp button to get the integration instructions of your bot.
### Configuration
You can customize how your bot behaves on WhatsApp in the `Configure integration` section
**Session expiration timeout**: A number from 0 to 48 which is the number of hours after which the session will expire. If the user doesn't interact with the bot for more than the timeout, the session will expire and if user sends a new message, it will start a new chat. The default is 4 hours.
**Start bot condition**: A condition that will be evaluated when a user starts a conversation with your bot. If the condition is not met, the bot will not be triggered.
## Collect position
You can ask for the user's location with a basic [Text input block](../../editor/blocks/inputs/text). It will be saved as a variable with the latitude and longitude with the following format: `, `.
## FAQ
You can integrate as many numbers as you'd like. Keep in mind that Typebot
does not provide those numbers. We work as a "Bring your own Meta
application" and we give you clear instructions on [how to set up your Meta
app](./create-meta-app).
Yes, you can. You will have to add a "Start bot condition" to each of your
bots to make sure that the right bot is triggered when a user starts a
conversation.
You integrate your typebots with your own WhatsApp Business Platform which
is the official service from Meta. At the moment, the first 1,000 Service
conversations each month are free. For more information, refer to
their documentation
## Troubleshooting
### After publishing the bot on my phone number, it doesn't reply back
It can happen that you configured your WhatsApp number, you send the first
message to try it out but it never replies back.
To troubleshoot this we suggest you to:
1. Make sure the bot works fine in [Test mode](#test)
2. Make sure the phone number you are using is not already used in WhatsApp Business app.
If it is, you won't be able to use the same number to use with Typebot. The process of associating a phone number to Typebot blocks that number from being used for a regular WhatsApp account. Even though we recommend to use a dedicated phone number number for Typebot, you can migrate your phone number registered with WhatsApp Business app by deleting your WhatsApp Business app account. It should unlock the number after 24 hours.
3. Delete the phone number configuration on Typebot and configure it again while making sure you read all the instructions thoroughly.
4. Make sure you don't have any Start conditions or that your first message is matching the condition
5. If using a test phone number, make sure the phone number you are using to send the first message is in the list of allowed numbers of that test phone number.
# Audio
Source: https://docs.typebot.com/editor/blocks/bubbles/audio
The Audio bubble block allows you to play a recorded audio to your user. You can upload an audio file or directly paste a URL.
## Troobleshooting
### The first audio bubble is not autoplaying
That is expected. Most web browser have a policy that prevents audio from playing automatically. The user needs to interact with the page before the audio can be played.
### The audio is not playing on iOS / Safari
It most likely means that your audio file is malformed. Depending on where the file comes from, you need to make sure the encoding is done correctly. To check if the file is correctly encoded you should be able to download it and play the file locally on your computer.
# Embed
Source: https://docs.typebot.com/editor/blocks/bubbles/embed
The Embed bubble block allows you to display a website or an iframe to your user. You can paste a video URL from many sources including YouTube, Vimeo, and mp4.
Not all websites allow embedding. If you see a blank space, it means the
website you're trying to embed doesn't allow it.
## Embed a PDF hosted on Google Drive
For this, you'll need to select the pdf file you want to embed. Right click > Preview > More actions > Open in a new window. Now click More actions > Embed item.
Copy the embed code and paste it in the Embed bubble block configuration.
## Wait for event
Enable this if you are the owner of the website you want to embed and would like to continue the bot flow only when an event from the embed is sent to the bot. This event dispatch needs to be executed in the embed website. Here is an example:
```js theme={null}
window.parent.postMessage(
{ name: 'My event', data: 'Custom data passed to the typebot variable' },
'*'
)
```
You can choose the name of the event, it needs to match what you've set in the Embed bubble block configuration.
# Image
Source: https://docs.typebot.com/editor/blocks/bubbles/image
The Image bubble block allows you to display an image to your user. You can upload an image, paste a URL or choose a GIF from the Giphy native integration.
# Text
Source: https://docs.typebot.com/editor/blocks/bubbles/text
The Text bubble block allows you to display a simple text bubble to your user. They can be chained and it will create a smooth animation:
## Insert a link
You can insert a link in your text bubbles using the link icon in the editor:
You can insert any links starting with `http:`, `https:`, `mailto:`, `tel:` or `sms:`. It can also be a variable.
# Video
Source: https://docs.typebot.com/editor/blocks/bubbles/video
The Video bubble block allows you to display a video to your user. You can paste a video URL from many sources including YouTube, Vimeo, and mp4.
## Video service detection
When you paste a video URL, Typbot will automatically detect the video service and parse it with the proper iframe settings. It currently works with:
* YouTube (video and shorts)
* Vimeo
* TikTok
* Gumlet
* OneDrive
Feel free to [suggest a missing service in the feedback board](https://feedback.typebot.io/).
For missing services, you can instead add an Embed bubble and paste the iframe code.
### Limitations
* YouTube clips are not supported as we can't transform it to embed URL automatically. To embed a YouTube clip, you can use the [Embed bubble](/editor/blocks/bubbles/embed) and paste the iframe code that can be found in Youtube under the "Share" > "Embed" button.
# Buttons
Source: https://docs.typebot.com/editor/blocks/inputs/buttons
The Buttons input block allows you to offer your user predefined choices, either single choice options or multiple choices
## Single choice
Single choice input allows you to directly split your flow depending on what the user selects by linking any choice to a specific path in your flow.
Link the "Default" item to determine the default path independent of what the user chooses.
## Multiple choices
## Dynamic items
Instead of adding items manually, you can also display a dynamic list of items based on a variable.
This is useful when you want to display a list of items from another data source. For this to work, you first need to make sure the variable you are using contains a list of values. This list can be extracted from an integration block like Google Sheets.
## Item options
### Display condition
Allows you to conditionally display a specific button.
### Internal value
Allows you to assign an internal value for that specific button. If your user selects this button, the internal value will be saved in the variable you've set in the `Save answer` option.
## How to
### Add a "Other" button
Sometimes you want to allow your user to enter a value that is not in the predefined choices. You can do this by adding a "Other" button and connect it to a "Text" input block.
### Different replies based on multiple choices
If you'd like to have different replies based on the multiple choices the user selects. You will need to
1. Save the answer into a variable.
2. Add a "Condition" block
3. Add comparisons based on the value of this variable
# Cards
Source: https://docs.typebot.com/editor/blocks/inputs/cards
The Cards input block allows you to display a list of cards in a carousel.
A card can contain an image, a title, a description and several buttons.
## Display cards from variables
To display cards dynamically from variables. Make sure you have list variables. For example:
* `{{Images}}` => `["https://example.com/image1.png", "https://example.com/image2.png", "https://example.com/image3.png"]`
* `{{Titles}}` => `["Card 1", "Card 2", "Card 3"]`
* `{{Descriptions}}` => `["Description 1", "Description 2", "Description 3"]`
Simply add those variables to a single card in the flow editor and the 3 cards will be displayed in the bot.
## Save answer in variables
You can store parts of the selected card into variables. Open the Cards block settings and add a mapping, then choose what to extract and which variable to save it to. Add multiple rows if you want to store several fields.
Fields you can save:
* **Image URL**: the URL of the selected card image.
* **Title**: the selected card title.
* **Description**: the selected card description.
* **Button**: the label of the button the user clicked on the selected card.
* **Internal Value**: a hidden value defined per card, ideal for stable identifiers (IDs, slugs). Configure it in a card’s settings under "Internal value".
# Date
Source: https://docs.typebot.com/editor/blocks/inputs/date
The Date input block allows you to ask your user for a date. You can ask for a specific date or range and include time:
The input will use the native date picker depending on the device and browser used to answer the bot. For example on Firefox it looks like this:
## Format
The `Format` setting lets you customize the picked date format. Under the hood, it is done using the [date-fns](https://date-fns.org/) library. You can use any of the [formatting tokens](https://date-fns.org/docs/format) supported by the library.
Here are some examples:
```text theme={null}
yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
dd/MM/yy
dd/MM/yyyy HH:mm:ss
d.MM.yy
```
There are 4 tokens that cause most of the confusion:
* D and DD that represent the day of a year (1, 2, ..., 365, 366) are often confused with d and dd that represent the day of a month (1, 2, ..., 31).
* YY and YYYY that represent the local week-numbering year (44, 01, 00, 17) are often confused with yy and yyyy that represent the calendar year.
To help with the common confusion, on Typebot by default, we interpret the tokens `D` and `Y` as `d` and `y` respectively.
More information: [https://github.com/date-fns/date-fns/blob/main/docs/unicodeTokens.md](https://github.com/date-fns/date-fns/blob/main/docs/unicodeTokens.md)
# Email
Source: https://docs.typebot.com/editor/blocks/inputs/email
The Email input block allows you to ask your user for an email. It will check if it is properly formatted.
The retry message will be displayed whenever Typebot detected that the email is not properly formatted.
It won't check if the email address is **valid**. To do that, you will have to trigger a [HTTP request block](/editor/blocks/integrations/http-request) and call an email validation service API.
# File upload
Source: https://docs.typebot.com/editor/blocks/inputs/file-upload
The File upload input block allows you to collect files from your user.
The placeholder accepts [HTML](https://en.wikipedia.org/wiki/HTML).
## Size limit
There is a 10MB fixed limit per uploaded file. If you want your respondents to upload larger files, you should ask them to upload their files to a cloud storage service (e.g. Google Drive, Dropbox, etc.) and share the link with you.
## Visibility
This option allows you to choose between generating public URLs for the uploaded files or keeping them private. If you choose to keep the files private, you will be able to see the file only if you are logged in to your Typebot account.
Note that if you choose to keep the files private, you will not be able to use the file URL with other blocks like Attachment in the Send email block or others. These services won't be able to read the files.
By default, this option is set to `Auto`. This means that the files will be public if uploaded from the web runtime but private if uploaded from the WhatsApp runtime. Because on WhatsApp, the file is already uploaded to the WhatsApp server, so there is no need to also upload it to Typebot (only if you need to make the file URL publicly accessible).
## Allowed file types
You can chose to restrict accepted file types. Add file extensions in the "Allowed file types" field to set up a whitelist of file extensions.
We allow any value that is accepted by the [`accept` attribute of an HTML input of type `file`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept#unique_file_type_specifiers).
All files will be allowed by default if this field is empty.
# Number
Source: https://docs.typebot.com/editor/blocks/inputs/number
The Number input block allows you to ask your user for a number. You can configure a minimum, a maximum and a step:
## Format
This only affects how the number is displayed to the user when he submitted the answer in a bot.
You can choose the format for the captured number. By default, the number is formatted as a decimal value following user's locale preferences. You can override this behavior to format it as a currency, a percentage, a scientific number, etc.
# Payment
Source: https://docs.typebot.com/editor/blocks/inputs/payment
The Payment input block allows you to collect payment. You first need to add your Stripe:
## Connect Stripe account
After clicking on `Select an account > Connect new`, a configuration popup appears:
* Account name could be anything you'd like it's not something that has to come from Stripe.
* Test keys can be found here: [https://dashboard.stripe.com/test/apikeys](https://dashboard.stripe.com/test/apikeys)
* Live keys can be found here: [https://dashboard.stripe.com/apikeys](https://dashboard.stripe.com/apikeys)
Test keys will be used in the preview for testing purposes. Live keys will be used in the published bot.
If you'd still like to still use the test keys in the published bot you just need to also fill in the test keys into the live keys inputs.
*If you would like to simulate a successful payment, use test cards from the following list in Stripe -> [https://docs.stripe.com/testing?testing-method=card-numbers#cards](https://docs.stripe.com/testing?testing-method=card-numbers#cards)*
## Input configuration
Once you have a Stripe account, you can select it and configure your input:
Make sure to enable any payment method you'd like to appear in your Stripe dashboard at this URL: [https://dashboard.stripe.com/settings/payment\_methods](https://dashboard.stripe.com/settings/payment_methods).
This is where you can enable Cards, Apple Pay, Google Pay, Alipay, WeChat Pay etc.
# Phone
Source: https://docs.typebot.com/editor/blocks/inputs/phone-number
The Phone number input block allows you to ask your user for a phone number and make sure it is properly formatted. It will also make sure that the number is stored in a consistent format. You can choose the default country code or leave it to international:
# Picture choice
Source: https://docs.typebot.com/editor/blocks/inputs/picture-choice
The Picture choice input block allows you to offer your user predefined choices illustrated with a picture, either single choice options or multiple choices
For advanced configuration, check out the [Buttons block](./buttons) documentation. It works the same way.
# Rating
Source: https://docs.typebot.com/editor/blocks/inputs/rating
The Rating input block allows you to ask your user for a rating.
The rating input is very customizable, you can set a custom range, numbers or a custom icon, and bottom labels.
## NPS
You could for example configure it so that it collects the Net promoter score:
## Custom icon
To insert a custom icon, you'll need to insert SVG content. It should start with ``. You can find great open-source icons on [Feather](https://feathericons.com/)
# Text input
Source: https://docs.typebot.com/editor/blocks/inputs/text
The Text input block allows you to ask your user for a text answer.
## Short text input
By default the text input is expecting a short answer:
## Long text input
You can also ask your user for a longer text answer by enabling it in the input options:
## Input mode
The input mode option allows you to specify the type of virtual keyboard that should be displayed on mobile devices. This provides a better user experience by showing the most appropriate keyboard for the expected input.
Available input modes:
* **text**: Shows a standard keyboard
* **decimal**: Shows a numeric keypad with decimal support
* **numeric**: Shows a numeric keypad for whole numbers
* **tel**: Shows a telephone keypad
* **search**: Shows a keyboard optimized for search inputs
* **email**: Shows a keyboard optimized for email addresses
* **url**: Shows a keyboard optimized for URL entry
Input mode is a hint to the browser and may not be supported on all devices or browsers. It's particularly useful for mobile devices.
For more information, see the [MDN documentation](https://developer.mozilla.org/docs/Web/HTML/Reference/Global_attributes/inputmode).
## Allow attachments
This option, when enabled, allows users to attach files to their message. This is useful when you want to ask for a document or a picture attached to the user messages.
The generated URL will be stored in the defined variable.
## Allow audio clips
This option, if enabled, displays a microphone button when the text input is empty. This allows users to record a voice message and send it to the bot.
If supported, the recorded file will be a WebM file. If not, it will be an MP4 file (i.e. Safari).
# Time
Source: https://docs.typebot.com/editor/blocks/inputs/time
The Time input block allows you to ask your user for a time. You can chose between 12 hour and 24 hour format.
The input will use the native time picker depending on the device and browser used to answer the bot. For example on Chrome it looks like this:
# Website
Source: https://docs.typebot.com/editor/blocks/inputs/website
The Website input block allows you to ask your user for a URL. It will check if it is properly formatted.
The retry message will be displayed whenever Typebot detected that the email is not properly formatted.
It won't check if the email address is **valid**. To do that, you will have to trigger a [HTTP request block](/editor/blocks/integrations/http-request) and call an email validation service API.
# Anthropic
Source: https://docs.typebot.com/editor/blocks/integrations/anthropic
## Create Message
With the Anthropic block, you can create chat messages based on your user queries and display the answer back to your typebot using Claude AI.
Similarly to the OpenAI block, this integration comes with a convenient message type called **Dialogue**. It allows you to easily pass a sequence of saved assistant / user messages history to Claude AI:
Then you can give the Claude AI block access to this sequence of messages:
Finally, save the response of the assistant to a variable in order to append it in the chat history and also display it on your typebot.
## Vision support
`Create Chat Message` and `Ask Assistant` blocks support vision. This means that Typebot automatically detects images URL in any user message provided to OpenAI and parse it. The URL needs to be isolated from the rest of the text message to be properly detected. Here is an example of a message with an image URL:
If the selected model is [not compatible with vision](https://docs.anthropic.com/en/docs/vision), the image URL will be parsed as a plain text message.
```
What's in this picture?
https://domain.com/image.png
```
# Blink
Source: https://docs.typebot.com/editor/blocks/integrations/blink
The Blink integration allows you to interact with your [Blink](https://joinblink.com) workplace communication platform directly from your typebot. You can retrieve user information and send rich feed events to keep your team informed and engaged.
## Authentication
To get started, you'll need to create a Blink app and generate an API token:
1. Follow the [official Blink instructions](https://developer.joinblink.com/docs/creating-an-integration) to create your integration
2. Generate an app token from your Blink admin dashboard
3. Add your app token to the Typebot credentials section
## Get Users
The "Get Users" action allows you to retrieve user information from your Blink workspace. You can filter users by either User ID or Employee ID.
### Configuration
* **Filter**: Choose between filtering by "User ID" or "Employee ID"
* **Save in variables**: Select which user data fields to save in your typebot variables
### Available User Data
The block can retrieve the following user information:
* **Email addresses**
* **Company names**
* **First and last names**
* **Display names**
* **Initials**
* **Job titles**
* **Profile photo IDs**
* **Timezones**
* **Manager IDs**
* **Department names**
* **Account statuses**
* **User IDs**
* **Employee IDs**
## Send Feed Event
The "Send Feed Event" action allows you to create rich, interactive cards in your Blink feed. These cards support various content types and interactive elements.
### Basic Configuration
* **Category ID**: The Blink category where the event should be posted
* **Ribbon Color**: Hex color code for the card's ribbon (e.g., #FF0000)
* **Allow Comments**: Enable/disable commenting on the feed event
* **Allow Reactions**: Enable/disable reactions on the feed event
### Card Content Types
The Blink integration supports a rich variety of content types for your feed cards. For comprehensive UI options and examples, refer to the [official Blink CardKit documentation](https://developer.joinblink.com/docs/cardkit).
### Targeting
* **User IDs**: Specific users who should see this feed event
* **Group IDs**: Specific groups who should see this feed event
### Push Notifications
Optionally configure a push notifications to receive whenever the feed event is posted.
# Chatwoot
Source: https://docs.typebot.com/editor/blocks/integrations/chatwoot
The Chatwoot integration block allows you to open a Chatwoot widget to allow your user to directly talk to a human. It allows you to add a Live Chat layer on your typebot.
## Requirements
For this integration, you need a Chatwoot account and create a "Website" inbox:
## Setup
Insert a Chatwoot block where you want to trigger the widget:
To find your website token, head over to Chatwoot in your Inbox settings:
You can prefill user information by adding collected variables to the "Set user details" inputs.
For example, if you set the "Email" input to "[john@gmail.com](mailto:john@gmail.com)" then Chatwoot will automatically associate this email to the current user.
## Custom attributes
You can add these custom attributes that Typebot will automatically fill in for you:
### Result URL
You can link the current result URL to the Chatwoot conversation by creating this custom attribute:
### Set user behavior
If you are prefilling user information, by default, if you leave the ID input empty, it will set the Chatwoot user ID as either the `Email` or the Result ID.
Setting the `Email` as the ID allows us to avoid having contact not properly merged together ([https://github.com/chatwoot/chatwoot/issues/2811](https://github.com/chatwoot/chatwoot/issues/2811))
# Dify.AI
Source: https://docs.typebot.com/editor/blocks/integrations/dify-ai
This block allows you to integrate your Dify.AI's assistant in your typebot.
## Create Chat Message
This action sends a user message to your agent. Then you can save `Answer` to a variable and display it in your typebot.
You are expected to provide the following parameters:
* `Query`: The user message you want to send to your agent.
* `Conversation ID`: The conversation ID you want to use for this message. If you don't provide one, a new conversation will be created. This variable content will be updated automatically if a new conversation is created.
* `User`: The user email used to identify the user in the conversation.
## Query Knowledge Base
This action queries your Dify.AI's knowledge base for the most relevant documents based on a query. This query could be the last user message to look for content that is relevant to the user's reply for example.
The retrieved chunks of information can be then saved into a variable that you can use in your typebot, for example you can add the chunks to the context of your AI block to help it answer the user's query.
# ElevenLabs
Source: https://docs.typebot.com/editor/blocks/integrations/elevenlabs
This block allows you to integrate ElevenLabs API into your typebot.
## Convert text to speech
Allows you to transform a text into a speech using ElevenLabs voices and models. This action automatically create a temporary link to the audio file. This link can be used in a [Audio bubble](../bubbles/audio) for example.
# Gmail
Source: https://docs.typebot.com/editor/blocks/integrations/gmail
The Gmail integration allows you to send emails directly through your Gmail account using Google's Gmail API. This provides a more reliable and feature-rich email sending experience compared to generic SMTP.
## Authentication
The Gmail integration requires OAuth2 authentication to access your Gmail account.
You can connect with Typebot default OAuth app or use your own credentials.
## Configuration Options
### Basic Settings
* **To**: The recipient's email address
* **Subject**: The email subject line
* **Body**: The email content (supports plain text and HTML)
* **Attachments**: Include file attachments (variable containing file URLs)
### Advanced Settings
* **Label**: Apply a Gmail label to the sent email
* **From**: Specify a custom sender name and email (e.g., "John Doe \<[john.doe@gmail.com](mailto:john.doe@gmail.com)>"). By default, the sender name and email is the one of the account used to connect to Gmail.
* **Reply To**: Set a different email address for replies
* **Thread ID**: Send email as a reply to an existing conversation thread
## Attachments
You can attach files to your Gmail emails by providing a variable that contains file URLs. The attachments can be:
* A single file URL (string)
* Multiple file URLs (array of strings)
Gmail has a 25MB total attachment size limit. Make sure your combined
attachments don't exceed this limit.
## Response Mapping
The Gmail block can save response data to variables:
* **Thread ID**: The conversation thread ID (useful for tracking email conversations)
# Google Analytics
Source: https://docs.typebot.com/editor/blocks/integrations/google-analytics
The Google Analytics integration block allows you to track a Google Analytics event at a given moment in your flow.
When your flow contains a Google Analytics block, under the hood it:
* Initialize GA and track a "Page view" event on page load.
* Track the event if any when the block is executed.
## Track conversions with Google Ads
To track conversions for your Google Ad, you can add a Google Analytics block whenever you'd like to trigger the conversion event with the following properties:
* Event action: conversion
* Send to: \
* Value (optional): a number to quantify the conversion
## Troubleshooting
To help you debug how your Google Analytics behaves, I suggest you add the [Google Analytics Debugger](https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna) extension to your browser.
# Google Sheets
Source: https://docs.typebot.com/editor/blocks/integrations/google-sheets
With the Google Sheets integration step, you can inject, update or get data from Google Spreadsheets. For an overview of how it works check out this video
In order to properly work, your spreadsheet must have its first row as a header row. And all header name should be unique. This is how the block knows which column to update:
## How to add the submission date to my row?
For this, you will need to set a new variable with the value "Now" before the Google Sheets block. Then you can simply use this variable in the Google Sheets block.
## Advanced
## Limitations
Google Sheets API is subject to hard limits set by Google:
* 60 read requests per minute
* 60 write requests per minute
Knowing that, we suggest that you limit the number of Google Sheets blocks you use in your bot. If you need to get the data from multiple sheets, we suggest that you first aggregate the data in a single sheet and then use the Google Sheets block to get the data from that single sheet.
## Troubleshooting
The Google sheets block didn't insert or update a row but was supposed to? Make sure to check the [logs](/results/overview#logs). If you still can't figure out what went wrong, shoot me a message using the chat button directly in the tool 👍
# HTTP Request
Source: https://docs.typebot.com/editor/blocks/integrations/http-request
The HTTP Request block allows you to send an HTTP request to a 3rd party service. This is useful to send information from the bot to another service or to fetch information from another service and use it in the bot.
## Make an API request and fetch data
This gets more technical as you'll need to know more about HTTP request parameters.
Lots of services offer an API. They also, most likely have an API documentation. Depending on the parameters you are giving the HTTP request block, it should return different info from the 3rd party service.
## Custom body
You can set a custom body with your collected variables. Here is a working example:
```json theme={null}
{
"name": "{{Name}}",
"email": "{{Email}}"
}
```
### Example with a dummy API: CREATE and GET
This video provides a step-by-step guide to successfully configure HTTP request blocks in Typebot.
I demonstrate how to configure the HTTP request block, including the URL, method, and custom body. I also show you how to test the request and save the newly created employee ID. Finally, I explain how to implement the find employee by ID endpoint and map the employee name to a variable.
### Example: fetch movie information
Let's create a bot that ask for a movie and retrieve its informations (By sending an HTTP request to the [OMDB API](http://www.omdbapi.com/)).
From the documentation, I know that by calling this specific URL: [http://www.omdbapi.com/?t=Star%20Wars\&apikey=1eb4670b](http://www.omdbapi.com/?t=Star%20Wars\&apikey=1eb4670b), it will search for "Star Wars" movie information and return JSON data.
What I need in my case is instead of inserting "Star Wars", I'd like to insert a Typebot variable:
Then, we can set a test value for our variable (it will replace the variable with this value only for the "Test the request" button):
Hit the "Test the request" button and then we can save the result in multiple variables:
Then we can use these variables to display dynamic content in the next bubbles:
Possibilities are endless when it comes to API calls, you can litteraly call any API and fetch any data you want.
Feel free to ask the [community](https://typebot.io/discord) for help if you struggle setting up a Webhook block.
## Call a Webhook URL
Your 3rd party service (Make.com, Zapier, etc) is giving you a Webhook URL.
You only have to paste this URL in the Webhook block and click on "Test the request". By default the 3rd party service will receive a snapshot of what the bot could send.
You can also decide to customize the request sent to the 3rd party service.
## Timeout
By default, the Webhook block will wait 10 seconds for the 3rd party service to respond. If it doesn't respond in time, the block will fail. You can customize this timeout value in the "Advanced params" section of your Webhook block settings.
## Troubleshooting
The Webhook block request fail or didn't seem to trigger? Make sure to check the [logs](/results/overview#logs). If you still can't figure out what went wrong, shoot me a message using the chat button directly in the tool 👍
You can use tools like [Webhook Tester](https://webhook-test.com/) to see payloads of webhooks for debugging and troubleshooting.
# Make.com
Source: https://docs.typebot.com/editor/blocks/integrations/make-com
The Make.com integration block allows you to trigger a scenario at a given moment in your flow.
1. Insert a Make.com block where you want to trigger the scenario:
2. Follow the instructions on Make.com to create and enable your scenario.
3. Run the scenario on Make.com.
4. Go back to Typebot, click on your Make.com block and click on "Test the request".
5. The scenario will be triggered on Make.com.
## Return data from Make.com
You can return data from Make.com by adding a "Webhook response" module at the end of your scenario, on this node you can set the body of the response with whatever Make.com values you want.
Once you are ready to try out the webhook, hit the `Run once` button. This will make the scenario to wait for a request to be made to the webhook URL.
At this point, head over to Typebot and hit the `Test the request` button. It will execute the Make.com scenario and you should see the response from Make.com.
Now you can map this data to variables in Typebot.
## Video tutorial
# Meta pixel
Source: https://docs.typebot.com/editor/blocks/integrations/meta-pixel
The Pixel integration block allows you to add a Meta pixel to your bot and track specific events.
When your flow contains a pixel block, under the hood it:
* Initialize the pixel and track "PageView" event on page load.
* Track the event if any when the block is executed.
# Mistral AI
Source: https://docs.typebot.com/editor/blocks/integrations/mistral
Similarly to the [OpenAI block](./openai), this block allows you to chat with Mistral's AI models.
Create your Mistral account here: [https://console.mistral.ai](https://console.mistral.ai).
## Create chat completion
With the Mistral AI block, you can create a chat completion based on your user queries and display the answer back to your typebot.
This action comes with a convenient message type called `Dialogue`. It allows you to easily pass a sequence of saved assistant / user messages history to Mistral AI
## Troobleshooting
* If you get HTTP 401 error while loading the Mistral models, it means your API key is still not propagated on Mistral's side. Please wait a few minutes and try again.
* If you get a rate limit error, make sure to add a subscription to your Mistral account. You can do so by going to your [Mistral billing section](https://console.mistral.ai/billing/) and clicking on the `Subscribe` button.
# NocoDB
Source: https://docs.typebot.com/editor/blocks/integrations/nocodb
With the NocoDB block, you can create, update or get data from your NocoDB tables.
## How to find my `Table ID`?
To find your `Table ID`, you need to go to your NocoDB dashboard and click on the 3 dots button next to your table name.
## Search Records
This action allows you to search for existing records in a table. It requires your `Table ID` and can optionally take a `View ID` to search in a specific view.
You can configure the filter to return `All`, `First`, `Last` or `Random` found records.
Then all you need to do is to map the found fields to variables that you can re-use on your bot.
# OpenAI
Source: https://docs.typebot.com/editor/blocks/integrations/openai
## Create chat completion
With the OpenAI block, you can create a chat completion based on your user queries and display the answer back to your typebot.
This integration comes with a convenient message type called **Dialogue**. It allows you to easily pass a sequence of saved assistant / user messages history to OpenAI:
Then you can give the OpenAI block access to this sequence of messages:
### Tools
The tools section allows you to add functions that the OpenAI model can execute. Here is an example of a function named `getWeather` that returns 'Sunny and warm' if you ask about the weather of Paris and 'Rainy and cold' if you ask for any other city 😂.
A more useful example would be, of course, to call an API to get the weather of the city the user is asking about.
As you can see, the code block expects the body of the Javascript function. You should use the `return` keyword to return value to give back to OpenAI as the result of the function.
If you'd like to set variables directly in this code block, you can use the [`setVariable` function](../logic/script#setvariable-function).
A function is executed on the server so it comes with [some limitations listed
here](../logic/script#limitations-on-scripts-executed-on-server).
## Ask Model
This action uses OpenAI's [Responses API](https://platform.openai.com/docs/api-reference/responses) to generate model responses with optional built-in tools and multi-turn conversation support.
### Basic setup
Select a **Model** (e.g. `gpt-5.4`), write a **Message** (typically the user's input), and optionally provide **Instructions** (system-level prompt for the model).
### Multi-turn conversations
To remember conversation history across messages, assign a variable to the **Response ID** field. If the variable is empty, a new conversation is started. On each response, the variable is automatically updated so the next invocation continues the same conversation.
### Built-in tools
You can enable the following OpenAI built-in tools in the **Built-in tools** section:
* **File Search** — select one or more vector stores from your OpenAI account. The model will search them for relevant content when answering.
* **Web Search** — let the model search the web for up-to-date information.
* **Code Interpreter** — let the model write and execute Python code.
### Functions
The **Functions** section lets you define custom functions the model can call. Each function has a name, description, typed parameters, and a JavaScript code block that returns a value.
The code block expects the body of a Javascript function. Use the `return` keyword to return a value back to the model.
If you'd like to set variables directly in this code block, you can use the [`setVariable` function](../logic/script#setvariable-function).
A function is executed on the server so it comes with [some limitations listed
here](../logic/script#limitations-on-scripts-executed-on-server).
:::note
**Migrating from Ask Assistant?** The Ask Assistant action (based on the deprecated OpenAI Assistants API) will be removed in August 2026. To migrate, create a new Ask Model block and configure the model, instructions, and tools directly — the Responses API no longer requires an assistant ID.
:::
## Create speech
This action allows you to transform a text input into an audio URL that you can reuse in your bot.
:::note
The generated audio URLs are temporary and expire after 7 days. If you need to store them, make sure to download them before they expire.
:::
## Create transcription
This action allows you to transcribe a audio URL into text.
You can optionally select a model (defaults to `whisper-1` for existing flows).
Provide a **Prompt** to guide the transcription (for example, include a list of
domain-specific terms or proper nouns).
## Generate variables
This action allows you to set variables based on a prompt.
Let's you want to want to extract a specific bit of information based on user's last message. You could use this block action to extract for example his name. To do that you could add the following prompt:
```txt theme={null}
Extract user's information from user's last message: "{{Last message}}"
```
This you could provide for example the following variables: `Name`, `Email`
If the `Last Message` variable is set to "My name is John and my email is [john@gmail.com](mailto:john@gmail.com)", then the `Name` and `Email` variables will be set to `John` and `john@gmail.com` respectively.
## Using Multiple Open AI Blocks: Tips and Tricks
In this video, I discuss some important things to keep in mind when using multiple Open AI blocks consecutively. I provide an example where we ask the user for a topic, generate a summary, and display a list of authors.
I explain that streaming messages is not possible when they are prefixed or suffixed by text, and that all blocks need to compute before displaying anything.
I also demonstrate how formatting can be affected by the presence of text before a message. Watch this video to learn how to optimize your use of multiple Open AI blocks.
## Vision support
`Create Chat Message` and `Ask Model` blocks support vision. This means that Typebot automatically detects images URL in any user message provided to OpenAI and parse it. The URL needs to be isolated from the rest of the text message to be properly detected. Here is an example of a message with an image URL:
If the selected model is [not compatible with vision](https://platform.openai.com/docs/models), the image URL will be parsed as a plain text message.
```
What's in this picture?
https://domain.com/image.png
```
So you can append any attachments provided by the user to the Dialogue variable and the model will automatically detect the image URL.
## Troobleshooting
### Error message: "OpenAI block returned error"
It means your OpenAI block is not configured properly. Please check the following:
* You have selected an OpenAI account
* You have at least 1 **user** message or a **Dialogue** message set up.
### It returns an empty message
It most likely mean that you exceeded your OpenAI free quota. Add a payment method to your OpenAI account to continue using it.
# Pabbly Connect
Source: https://docs.typebot.com/editor/blocks/integrations/pabbly-connect
The Pabbly Connect integration block allows you to trigger a workflow at a given moment in your flow.
1. Insert a Pabbly Connect block where you want to trigger the workflow:
2. Follow the instructions on Pabbly Connect
3. It should give you a URL that you need to paste into the block configuration.
4. Pabbly Connect block should be properly configured.
# PostHog
Source: https://docs.typebot.com/editor/blocks/integrations/posthog
With the PostHog block, you can send events to PostHog and trigger your PostHog workflows. It uses the PostHog Node.js library to send server side events to PostHog, so that it works on non web browser devices.
## How to find my `Project API Key` and `API Host`?
To find your `Project API Key`, you need to go to your PostHog Settings page, in the General tab, you will find the Project API key.
## Identify Group
This action allows you to identify a group in PostHog. It requires the group `Type` and `Key`, and can optionally take `Distinct ID` and a set of `Properties` that will be added to the group profile.
## Capture
This action allows you to capture a custom event, or native PostHog events, such as a page view, a screen view, etc. It requires the `Event` name to be set. It can optionally take a `Distinct ID` set of `Properties` and `Person properties` to set properties to the associated person alongside the captured event, as well as associated groups information.
# Segment
Source: https://docs.typebot.com/editor/blocks/integrations/segment
With the Segment block, you can send events to Twilio's Segment and trigger your Segment workflows. It uses the Segment Analytics Node.js library to send server side events to Segment, so that it works on non web browser devices.
## How to find my `Write Key`?
To find your `Write Key`, you need to go to your Segment dashboard and click on the `Sources` tab. Then click on the `API Keys` button of the source you want to use.
## Identify User
This action allows you to identify a user in Segment. It requires the `User ID` and `Email` and can optionally take a set of `Traits`.
## Alias
This action allows you to alias a user in Segment. It requires the `Previous ID` and the `User ID`.
## Event
This action allows you to track an event in Segment. It requires the `Event Name` and `User ID`, and can optionally take a set of `Properties`.
## Page
This action allows you to send a page view event to Segment. It requires the Chatbot `Name` and can optionally take a `Category` name and also a set of `Properties`.
# Send email
Source: https://docs.typebot.com/editor/blocks/integrations/send-email
If you want to receive an email notification each time a user completes the bot or if you want to send a recap to the user, the Email block is made for you:
If you are on the Free plan, you will have to configure your own SMTP account first. This is to prevent spam and abuse of the in-built Typebot email sender. You can find a bunch of SMTP providers with generous Free tiers that will provide SMTP credentials to use within Typebot. Here are a few examples:
* [SendGrid](https://sendgrid.com/)
* [Mailgun](https://www.mailgun.com/)
* [Amazon SES](https://aws.amazon.com/ses/)
* [Resend](https://resend.com/)
If you subscribed to a paid plan, you can easily send emails from `notifications@get-typebot.com` without additional configuration.
The default email content is based on what your new lead has replied to. It will look like this:
But you can also write your own text/html email content.
## Attachments
You can attach files to your email with the Attachments option. Make sure that it points to a variable that is linked to a File upload input block.
## Troubleshooting
You are supposed to receive an email but it doesn't get to your inbox? Make sure to check the [logs](/results/overview#logs). If you still can't figure out what went wrong, shoot me a message using the chat button directly in the tool 👍
# Zapier
Source: https://docs.typebot.com/editor/blocks/integrations/zapier
The Zapier integration block allows you to trigger a zap at a given moment in your flow.
1. Insert a Zapier block where you want to trigger the Zap:
2. Follow the instructions on Zapier to create and enable your Zap.
3. Zapier block should be properly configured.
## Video tutorial
# Zendesk
Source: https://docs.typebot.com/editor/blocks/integrations/zendesk
## Zendesk Messaging
With the Zendesk Chat block, you can open a Zendesk Messaging live chat window to allow a user to chat with a Zendesk agent.
## How to find my Zendesk `Key ID` and `Secret Key`?
To configure your Web Widget or mobile SDK for visitor authentication, you first need a signing key. A signing key is a type of credential which is comprised of a key id (kid) and a shared secret.
You can view, create, and delete signing keys by clicking the Account icon in the Admin Center sidebar, and then selecting End user authentication under the Security heading ( you will need to be a Zendesk Admin). The shared secret will only be displayed in its entirety when the signing key is first created.
Learn more here: [https://developer.zendesk.com/documentation/zendesk-web-widget-sdks/sdks/web/enabling\_auth\_visitors/#generating-a-signing-key](https://developer.zendesk.com/documentation/zendesk-web-widget-sdks/sdks/web/enabling_auth_visitors/#generating-a-signing-key)
## Open Web Widget
This action opens the Messenging Web Widget. It requires the Web Widget `Key` to be set. You can find the key by going to `Channels -> Messaging`, then click on the Web Widget you wish to configure. Scroll down to 'Installation' and expand that section. In the script code block, copy the `key` value and use that for the `Key` setting.
Note, this only works on web clients.
If the `User ID` option is set, a JWT token will be created and passed to Zendesk, to authenticate the user in Zendesk. If you need `Name` or `Email` included in the JWT token, set those options also.
# AB Test
Source: https://docs.typebot.com/editor/blocks/logic/ab-test
The AB Test block allows you to split the path in 2 randomly. It's great way to test the performance of 2 different paths.
## More than 2 paths
You can stack multiple AB test blocks to add more random paths
# Condition
Source: https://docs.typebot.com/editor/blocks/logic/condition
The Condition block allows you to split your flow in two based on a condition.
A condition can contain different comparisons that are evaluated in order and linked with a logical operator: 'AND' or 'OR'.
## Operators
Will match if the provided value is strictly equal to the value.
Will match if the provided value is not equal to the value.
Will match if the provided value contains the value. If a list is provided, it
will match if the list has at least one element in common with the value.
Same as `Contains` but will match the inverse.
Will match if the provided value is greater or equal than the value. If the
variable you provided is a list, it will execute the condition on the length
of the list.
Will match if the provided value is less or equal than the value. If the
variable you provided is a list, it will execute the condition on the length
of the list.
Will match if the provided value is not null or undefined and not an empty
string.
Will match if the provided value is null, undefined, or an empty string.
Will match if the provided value starts with the value.
Will match if the provided value ends with the value.
Value should start and end with `/` and contain a valid regex pattern.
Example:
* `/^hello$/` will match if the string is strictly equal to "hello".
* `/hello/` will match if the string contains "hello". Like "hello world".
* `/hello/i` will match if the string contains "hello" case-insensitive. Like "Hello world".
* `/[0-9]+/` will match if the string contains one or more digits. Like "123".
Same as `Matches regex` but will match if the provided value does not match
the regex pattern.
# Jump
Source: https://docs.typebot.com/editor/blocks/logic/jump
The jump block allows you jump to a specific block. This comes handy if you want to keep your flow clean
# Redirect
Source: https://docs.typebot.com/editor/blocks/logic/redirect
The Redirect logic block allows you to redirect your user to a given URL either on the current tab or in a new tab.
Safari and iOS devices will block a redirect in a new tab by default so a
popup will be displayed to the user. Make sure to test your redirect logic
block on these devices.
# Return
Source: https://docs.typebot.com/editor/blocks/logic/return
The Return block is used to bring the conversation back to where it left off before a temporary jump happened.
Whenever you "jump" to another part of your flow (using a Jump block or an Event trigger), the conversation temporarily moves away from the main path.
By placing a Return block, you tell Typebot:
> "Okay, I'm done here — now go back to where the user was."
## When should you use a Return block?
You should use a Return block whenever you want the conversation to resume its previous flow after a jump.
✅ After using a [Jump block](./jump).
✅ Inside an Event-triggered subflow.
## When is a Return block NOT needed?
Some blocks automatically return to where they were without needing a Return block.
You do NOT need a Return block when using the [Link to Typebot block](./typebot-link). It automatically returns when the linked flow finishes.
## Example use cases
* You use a Jump block to temporarily ask the user a few clarification questions, then you place a Return block to resume the original conversation.
# Script block
Source: https://docs.typebot.com/editor/blocks/logic/script
The "Script" block allows you to execute Javascript code.
This block doesn't allow you to create a custom visual block
Variables in script are not parsed, they are evaluated. So it should be treated as if it were real javascript variables.
You need to write `console.log({{My variable}})` instead of `console.log("{{My variable}}")`
## `setVariable` function
If you want to set a variable value with Javascript, the [Set variable block](./set-variable) is more appropriate for most cases.
However, if you'd like to set variables in a Script block, you can use the `setVariable` function in your script:
```js theme={null}
if({{My variable}} === 'foo') {
setVariable('My variable', 'bar')
} else {
setVariable('My variable', 'other')
}
```
The `setVariable` function is only available in script executed on the server, so it won't work if the `Execute on client?` is checked.
## Limitations on scripts executed on server
Because the script is executed on a isolated and secured environment, there are some limitations.
* Global functions like `console.log`, `setTimeout`, `setInterval`, etc. are not available
* The `fetch` function behavior is slightly different from the native `fetch` function. You just have to skip the `await response.text()` or `await response.json()` part.
```js theme={null}
// ❌ This throws an error
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const data = await response.text()
// ✅ This works
const data = await fetch('https://jsonplaceholder.typicode.com/todos/1')
```
`response` will always be a `string` even if the the request returns a JSON object. If you know that the response is a JSON object, you can parse it using `JSON.parse(response)`.
```js theme={null}
// ❌ This throws an error
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const data = await response.json()
// ✅ This works
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const data = JSON.parse(response)
```
* You can't use `import` or `require` to import external libraries
* You don't have access to browser APIs like `window`, `document`, `localStorage`, etc. If you need to use browser APIs, you should check the `Execute on client?` option so that the script is executed on the user's browser.
## Examples
### Reload page
```js theme={null}
window.location.reload()
```
### Redirect if a variable has a specific value
```js theme={null}
if({{Category}} === 'qualified') {
window.location.href = 'https://my-site.com'
}
```
Do you need to do something but you're not sure how to? [Join the Discord server](https://typebot.io/discord) and get instant help!
# Set variable
Source: https://docs.typebot.com/editor/blocks/logic/set-variable
The "Set variable" block allows you to set a particular value to a variable.
## Custom
You can set your variable with any value with `Custom`. It can be any kind of plain text but also **Javascript code**.
### Expressions with existing variables
It means you can apply operations on existing variables.
Add a value to your variable:
```
{{Score}} + 5
```
Compute a sum of variables:
```
{{Score}} + {{Answer}}
```
Multiply variables together:
```
{{Score}} * {{Multiplier}}
```
Compute a percentage:
```
{{Score}} * 100 / {{Max Score}}
```
Extract the first name from a full name:
```
{{Full name}}.split(' ')[0]
```
Transform existing variable to upper case or lower case:
```
{{Name}}.toUpperCase()
```
```
{{Name}}.toLowerCase()
```
This can also be Javascript code. It will read the returned value of the code and set it to your variable.
```js theme={null}
const name = 'John' + 'Smith'
return name
```
If you don't provide the `return` keyword then it will be automatically prepended to the beginning of your code.
```js theme={null}
'John' + 'Smith'
```
is the same as
```js theme={null}
return 'John' + 'Smith'
```
Variables in script are not parsed, they are evaluated. So it should be treated as if it were real Javascript variables.
So, if you write `"{{My variable}}"`, it will parse the variable ID (something like `vclfqgqkdf000008mh3r6xakty`). You need to remove the double quotes to properly get the variable content value.
For example,
* ❌ `"{{URL base}}/path"` => `vclfqgqkdf000008mh3r6xakty/path`
* ✅ `{{URL base}} + '/path'` => `https://domain.com/path`
* ✅ `` `${{{URL base}}}/path` `` => `https://domain.com/path`
Variables content can either be a string or a list of strings. Check out
[Valid value types](../../variables#valid-value-types) for more information.
## Empty
Resets your variable as if it was never initialized.
## Append value(s)
A conveniant value that automatically transform your variable into a list of strings. It will append the value(s) to the list.
3 possible cases here:
* If the variable is empty, it will create a new array with the provided value(s)
* If the variable is not an array, it will create a new array with the existing value followed by the provided value(s).
* If the variable is an array, it will concatenate the provided value(s) to the existing array.
## Environment name
This will set your variable with either `web` or `whatsapp` depending on the environment.
## Device type
This will set your variable with either `desktop`, `tablet` or `mobile` depending on the device type. Under the hood, we uses a combination screen width, user agent and touch capabilities to detect the device type. You can find the code [here](https://github.com/baptisteArno/typebot.io/blob/e74b95fd65064b7e1c37f7fb789c316deb601d36/packages/bot-engine/src/blocks/logic/setVariable/executeSetVariable.ts#L322-L350)
## Transcript
This preset value will save the entire conversation transcript in a variable. It is super useful to provide context to an AI block or to send it as a recap with the [Send email](../integrations/send-email) block.
## Result ID
This will set your variable with the current result ID. The result ID is the ID that corresponds to a row of your [Results](../../../results/overview.mdx) table. It can be considered like a User ID for the currently chatting user.
## Yesterday, Now, Tomorrow
This will set your variable with the specified date and time in ISO format. You can optionally provide a time zone to convert the date to the specified time zone.
## Random ID
This will set your variable with a random ID with the CUID algorithm.
## Moment of the day
It will set your variable with either one of these values based on the user's time of the day: `morning`, `afternoon`, `evening`, `night`.
Then you can use this variable to conditionally display content:
## Map item with same index
This is a convenient value block that allows you to easily get an item from a list that has the same index as an item from another list.
When you are pulling data from another service, sometimes, you will have 2 lists: `Labels` and `Ids`. Labels are the data displayed to the user and Ids are the data used for other requests to that external service.
This value block allows you to find the `Id` from `Ids` with the same index as `Label` in `Labels`
## Phone number
Only available in WhatsApp. This will set your variable with the user's phone number.
## Contact name
Only available in WhatsApp. This will set your variable with the user's name.
## Pop / Shift
Pop removes the **last** item from the list variable that you provide and it will set the removed item into the "Popped item" variable. Shift does the same with the **first** item of the list. These are especially useful when you need to [create a loop](../../../guides/how-to-create-loops) that processes each item of a list.
## Save in results
By default, new variables are not persisted in the [Results](../../../results) table. They are only stored for the current user chat session. Enabling this option will save the variable in the `Results` table.
## Execute on client
This option is useful when you want to execute the custom code on the client side. This is only necessary when you need access the user's browser information. So, if you need access to `window`, `document`, `navigator`, etc., you should enable this option.
## Get user's geo location
For this you can provide the following custom code:
```js theme={null}
function getLocation() {
return new Promise((resolve) => {
navigator.geolocation.getCurrentPosition(
(position) =>
resolve(`${position.coords.latitude}, ${position.coords.longitude}`),
(error) => resolve('error'),
{ enableHighAccuracy: true, timeout: 5000 }
)
})
}
const coords = await getLocation()
// Check for error
if (coords === 'error') {
return 'Unable to get location'
}
return coords
```
This custom function can only work when it is executed on the client browser so you need to make sure to enable the "Execute on client" option.
# Link to typebot
Source: https://docs.typebot.com/editor/blocks/logic/typebot-link
The typebot link logic block allows you to go into another typebot flow. This ultimately helps keep your flows clean and be able to reuse a flow in multiple places.
## Share variables between bots
The existing variable values are automatically shared to the linked bot. It means that if this linked bot contains similar variable names, it will be automatically pre-filled with the values from the previous bot.
Example: My first bot asks for the user's name and stores it in the `Name` variable. Then, I link to another bot that displays a `Name` variable in a text bubble. This will display the name collected in the first bot.
## Merge answers
The Merge answers option allows you to merge the answers collected from a linked bot to the current bot. This is useful if you want to collect answers from multiple bots and then send them all at once to a third-party app. Or if you just want to collect all the answers into a unified results table.
# Wait
Source: https://docs.typebot.com/editor/blocks/logic/wait
The "Wait" block allows you to pause the conversation for a certain amount of seconds.
This can be useful if you want the bot to emphasize on what's been said or to wait before a redirection for example to make sure the user has read everything.
This should be used wisely. If you want the bot to write slower or faster in a
more general sense, you need to check the [Typing emulation
settings](/settings/overview#typing-emulation)
## Pause the flow
You can enable the "Pause the flow" option if you ever need to mark a pause in the flow.
Under the hood, typebot always compute all the blocks between each input blocks. But sometimes you may want to display some messages before a long-running action.
# Webhook
Source: https://docs.typebot.com/editor/blocks/logic/webhook
The **Webhook block** is often confused with the [HTTP Request block](/editor/blocks/integrations/http-request).
* Use the **Webhook block** when you want Typebot to **pause and wait** until an external service calls back Typebot.
* Use the **HTTP Request block** if you want Typebot to **immediately call an API** or trigger a N8N scenario, etc. and get a response back.
The Webhook block allows you to pause the conversation until a provided webhook URL is called.
This can be useful if you want to execute a long-running action that can take several minutes to complete.
## URLs
### Test
* Web:
```
https://typebot.io/api/v1/typebots/{typebotId}/blocks/{blockId}/web/executeTestWebhook
```
* WhatsApp:
```
https://typebot.io/api/v1/typebots/{typebotId}/blocks/{blockId}/whatsapp/{phone}/executeTestWebhook
```
Where `{phone}` is your phone number on which you test the bot. For example, if you provided `+33 601 020304`, `{phone}` should be `33601020304`, no spaces, no `+`.
### Production
No matter the environment, the webhook URL will be the same:
```
https://typebot.io/api/v1/typebots/{typebotId}/blocks/{blockId}/results/{resultId}/executeWebhook
```
Where `{resultId}` is the current user result ID. You can get this ID directly in your typebot flow using a [Set variable](/editor/blocks/logic/set-variable) block with the `Result ID` value.
## Authentication
The Webhook URL needs to be authenticated in order to work. See [API authentication](/api-reference/authentication) for more information.
# Overview
Source: https://docs.typebot.com/editor/blocks/overview
Blocks are the atomic building blocks of a typebot chat. You can chain any blocks together to create complexe conversation flows. When you drag and drop a block in the typebot flow, by default it will be inserted into a group that can have a title. Blocks are always contained in groups.
There are multiple block categories to make it easier to find the right block for your needs:
## Bubbles
Bubble blocks are used to show bubbles that can be used to display information to the user.
## Inputs
Input blocks are used to ask the user for input. It will stop the conversation and for the user to provide input.
## Logic
Logic blocks are used to perform background operations. They are not visible to the users.
## Integrations
Integration blocks are used to trigger external services operations.
Interested in implementing your own integration block? Head over to [The
Forge](/contribute/the-forge/overview) to easily create your block.
# Context menu
Source: https://docs.typebot.com/editor/context-menu
You can right-click on different elements on the builder to trigger a menu with different actions.
If you right-click on a group, you will see a menu with the following options:
* **Duplicate** to create a duplicated group with the same blocks and settings
* **Delete** to remove the group
If you right-click on a block, you will see a menu with the following options:
* **Duplicate** to create a duplicated block below the duplicated one with the same settings
* **Delete** to remove the block
If you right-click on an edge, you will see a menu with the following options:
* **Delete** to remove the edge
# Command Event
Source: https://docs.typebot.com/editor/events/command
This event allows you to trigger a specifc flow when a command is sent to the bot. This command can be sent with an [continueChat HTTP request](/api-reference/chat/continue-chat) with a `command` message type or with the [Typebot.sendCommand](/deploy/web/html-javascript#commands) function if your bot is embedded on a website.
Looking to trigger behavior when the user **types** a keyword like `restart` or `help`? Use a [Reply event](./reply) instead — the Command event is only for triggers sent programmatically from outside the chat. See the [user commands guide](/guides/user-commands) for a concrete example.
You assign a unique command name for each node and you can optionally resume the flow after the command is sent.
## Return to main flow
By default, when an event is executed, the session will end and not return to the main flow. Use a [Return block](/editor/blocks/logic/return) to return to the main flow. This allows you to have the flexibility to conditionally end the session.
# Invalid Reply Event
Source: https://docs.typebot.com/editor/events/invalid-reply
The **Invalid Reply Event** is triggered every time a user submits an invalid response to an input block — for example, an incorrectly formatted email or a number outside a defined range. It allows you to define a custom subflow that replaces the default "Invalid message. Please, try again." behavior.
This is useful when you want to handle invalid inputs in a more conversational, branded, or dynamic way — such as providing specific guidance, logging the error, or redirecting users.
## Supported inputs
This event is triggered by any input block that supports validation, including:
* Email
* Number
* URL
* Phone
* Date / Time\
...
## Variable mapping
* **Reply content**: The content of the invalid reply.
* **Input type**: The type of the current input. Can be `text`, `number`, `email`, `url`, `date`, `time`, `phone`, `buttons`, `picture choice`, `payment`, `rating`, `file`, `cards`.
* **Input name**: The name of the current input. If a variable is attached to the input, it will be the name of the variable. Otherwise, it will be the title of the group.
These variables can help you customize messages based on what the user did wrong (e.g., “It looks like **\{\{invalid value}}** is not a valid email”).
## Input blocks inside the event subflow
You can technically use input blocks inside the `Invalid Reply Event` subflow, but this is not recommended unless you plan to **manually handle flow redirection** using a Jump block.\
If your subflow includes inputs but doesn't use a Jump block, Typebot will still retry the original input block at the end — which could confuse users.
## Return to main flow
By default, when an event is executed, the session will end and not return to the main flow. Use a [Return block](/editor/blocks/logic/return) to return to the main flow. This allows you to have the flexibility to conditionally end the session.
## Example use cases
* Show a friendlier explanation of why the input is invalid (e.g., "Oops! That doesn't look like a real email").
* Track how many invalid attempts a user makes with a variable and show a warning after 3 tries.
* Redirect the user to a help flow if they keep entering invalid values.
# Reply Event
Source: https://docs.typebot.com/editor/events/reply
This event will trigger everytime a reply is received, meaning whenever a user replies to any input in the flow. This is triggered even before the reply is processed and validated. This is useful when you need to execute a specific flow / automation whenever the user replies to the bot.
Not sure whether to use a Reply event or a [Command event](./command)? Use **Reply** when the trigger comes from inside the chat (the user types or clicks something). Use **Command** when the trigger comes from outside the chat (a button on your website, an external webhook, etc.).
## Variable mapping
* **Reply content**: The content of the reply.
* **Input type**: The type of the current input. Can be `text`, `number`, `email`, `url`, `date`, `time`, `phone`, `buttons`, `picture choice`, `payment`, `rating`, `file`, `cards`.
* **Input name**: The name of the current input. If a variable is attached to the input, it will be the name of the variable. Otherwise, it will be the title of the group.
Type and name ultimately can help you filter the reply event by input type and/or name.
## Return to main flow
By default, when an event is executed, the session will end and not return to the main flow. Use a [Return block](/editor/blocks/logic/return) to return to the main flow. This allows you to have the flexibility to conditionally end the session.
## Example use cases
* Automatically end the session if the user replies with "end", "exit", "quit".
* Automatically trigger a feedback collection flow whenever a user replies with specific keywords like "feedback" "suggestion" or "comment".
* Implement user commands like `restart` or `help`. See the [user commands guide](/guides/user-commands) for a step-by-step recipe.
# Export / Import a typebot
Source: https://docs.typebot.com/editor/export-import
A typebot flow can be exported to a JSON file using the menu button at the top right of the builder:
Then this file can be imported when creating a new typebot by choosing "Import a file":
# Graph
Source: https://docs.typebot.com/editor/graph
The Graph is where you arrange your conversation flow and connect the Typebot [blocks](./blocks/overview) together.
## Gestures
In the user preferences, under the `Graph Gestures` section, you can choose between `Mouse` and `Trackpad` gestures.
### Mouse
**Select**: `Shift` + `Left click` drag
**Zoom**: `Ctrl` + `Mouse wheel`
**Pan**: `Left click` drag or `Mouse wheel` for vertical pan and `Shift` + `Mouse wheel` for horizontal pan
### Trackpad
**Select**: `Click` + drag
**Zoom**: Pinch
**Pan**: Use two finger
## Common pitfalls
### A block without an outgoing edge stops the flow
Every block (except the final one of a conversation) needs an outgoing edge connected to the next block or group. If a block has no outgoing edge, the conversation will stop right there, even if other groups exist below.
This is the most common cause of "my bot stops in the middle of the flow". The
editor does not display a visual warning when a non-terminal block has no
outgoing edge, so double-check that every block you expect to continue has a
connection.
# Publish
Source: https://docs.typebot.com/editor/publish
Once you publish your bot, its public URL will work and you can send it to anyone and start collecting results.
You can always modify your bot and the new changes won't be published as long as you don't hit the Publish button again.
* "Restore published version": drop your current changes and revert the bot to its published version.
* "Close typebot to new responses": close your typebot and your users will see the following message: "This bot is now closed."
* "Unpublish typebot": mark the typebot as unpublished and your users will see the following message: "The bot you're looking for doesn't exist"
# Share
Source: https://docs.typebot.com/editor/share
Your typebot flow can be publicly shared. For this, open the Share menu and enable the `Make the flow publicly available` option:
The flow can then be tested by non-authenticated guests. They are able to check all the options and can play the bot in preview mode.
# Variables
Source: https://docs.typebot.com/editor/variables
Variables are placeholders for content that you can then use anywhere in the Typebot. It's a very important concept to understand to truly create a customized experience for the user.
## Save an answer in a variable
You can tell your input block to save the answer into a variable and reuse then in a further bubble for example:
## Use variables
Once your variables are declared you can use theme **anywhere** in your bot. For example you can display it in a text bubble with the following syntax:
`{{My variable}}` where "My variable" is the name of your variable.
## Inline variable formatting
You can also decide to format your variable directly in the text bubble. For example if you want to display the variable "First name" in uppercase you can use the following syntax:
`{{={{My variable}}.toUpperCase()=}}`
When you insert `{{= ... =}}`, it means what's inside will be evaluated as JavaScript. So you can use any JavaScript inline function inside. The behavior is similar to the custom value in the Set variable block.
If you would like to get the first item of a list:
`{{={{My variable}}[0]=}}` or `{{={{My variable}}.at(0)=}}`
Likewise for last item:
`{{={{My variable}}.at(-1)=}}`
## Variables panel
You can access the variables panel by clicking on the "Variables" button in the top right corner of the editor:
In this panel you can see all the variables declared in your bot. There, you can easily rename, edit, delete your variables.
By default, a variable is not saved in the results table. You can change it by enabling the `Save in results` option in the Variables panel.
## Advanced concepts
Here is a quick video that showcases advanced concepts about variables:
### Prefilled variables
By default, any declared variables in the bot can be prefilled by passing initial values in the URL.
Let's say my typebot contains these variables:
* "Email"
* "First name"
They can be initialized in the URL as [URL parameters](https://www.semrush.com/blog/url-parameters/). If I'm launching my bot using this URL:
`https://typebot.io/my-bot?Email=test@test.com&First%20name=John` (Note that spaces in variable names should be replaced by `%20`)
Then the variables will be prefilled as following:
* Email => `test@test.com`
* First name => `John`
Prefilled variables in your bot can be used in the same way as any other variables. For example if the first bot question is "What is your email?", you can decide to add a Condition block just before the question to check if the email was already prefilled to avoid asking the user to submit it. Or if you prefer your user to double check their existing email, you can enable the [prefill input](/settings/overview#general) option in the settings.
Prefilling variables using the embed library is even easier. You need to add an object named `prefilledVariables` that contains a dictionary of your values. For example:
```js theme={null}
Typebot.initBubble({
typebot: `my-bot`,
prefilledVariables: {
Email: 'test@test.com',
'First name': 'John',
},
})
```
(Note that if your variable name contains spaces, it needs to be surrounded by quotes.)
### Hidden variables
Your typebot's variables don't have to be displayed to the user. You could create variables that are only used internally by the bot and displayed in your results. This allows you to add some context to a session for example a User ID, a `utm_source` parameter (in the case of a marketing campaign), or anything else.
You just have to make sure that the variables exist in the variables dropdown:
(This dropdown can be found in any place where you can add variables. It is global to your bot flow.)
Then the values will be available on the Results page in specific columns:
### Valid value types
Variables content can either be a text (`string`) or a list of texts (`string[]`).
```ts theme={null}
// ✅ Good
'Hello', ['item 1', 'item 2']
// ❌ Not good
2, true, { foo: 'bar' }
// Will automatically converted into
'2', 'true', '{ foo: "bar" }'
```
If you provide an object, number or boolean. It will always be converted into either a text
or a list of texts before the variable is saved into the database.
This limitation is intended. Variables should have simple content. It forces you to have a cleaner bot structure and to use the variable content in a more meaningful way.
In some cases, the variable content will be dynamically parsed to match its intended type. For example, if you provide a text that
looks like a number in a condition block, it will be converted into a number during the condition execution.
If you really need to save a complex content into a variable, for example an object, you can use the `JSON.stringify` function to convert it into a text. And whenever you are using the variable, you can dynamically parse it back into an object using `JSON.parse` in an [inline format](#inline-variable-formatting):
```ts theme={null}
{{=JSON.parse({{My object variable}})=}}
```
# FAQ
Source: https://docs.typebot.com/faq
## How Typebot executes the blocks between each user input?
## Why some of my results are empty?
Your typebot collects results as soon as your user answers the first input. If other inputs have a blank answer, it means the user never answered them and left the bot.
## How can I delete a block or an edge?
You can right-click on most elements in the graph to open up a contextual menu.
## Is human takeover is available on Typebot?
Live chat is not natively integrated. Typebot is specifically built for async chats. You can still have a human takeover feature using the [Chatwoot block](/editor/blocks/integrations/chatwoot). It will open a Chatwoot live chat box whenever the block is hit.
You can also implement great customer support with Typebot by using a ticketing system such as [Freshdesk](https://freshdesk.com/) or [Zendesk](https://www.zendesk.com/). You can create a ticket each time your user answers the bot.
## Is there an affiliate program available?
I'm not planning on having a Typebot affiliation program.
As a customer, I don't like when someone promotes a tool with an affiliation because we could think that the only reason he's promoting it is that he can win big comparing with other tools.
Natural recommendations resonate a lot more with me. My goal is to create the best user experience possible, so I really hope you will recommend Typebot for free. 🤝
## How can I change my password
Typebot doesn't store any password. Its login works with Github, Google, Facebook and Magic link email.
## Can I set a variable with the Script block?
No, the script block is only meant to execute a script. You can't set a variable with/in it. If you need to set a variable with some code, you can use the [Set variable block](/editor/blocks/logic/set-variable).
## I don't see my bots after login, where did they go?
Typebots live inside a workspace, and each account can belong to several workspaces. A common case is having a personal Free workspace and being invited to a team workspace: after login you land on one of them, and your bots may actually be in the other.
Open the workspace dropdown at the top-left of the dashboard and switch to the workspace that contains your bots.
If the expected workspace is missing from the dropdown, make sure you are logged in with the same email that was invited to the team workspace. See [workspace overview](/workspace) for more details.
## Is there a status page?
Yes. The public status page is available at [status.typebot.io](https://status.typebot.io). It reports uptime and incidents for the Typebot Cloud services (builder, viewer, API). You can subscribe there to get notified when an incident is opened or resolved.
## Can I have a persistent text input always visible at the bottom of the chat?
No. Typebot is a flow-driven conversation engine: the input shown at any moment is the one defined by the current block. There is no native way to display a persistent free-text input that stays visible outside of an input block.
If you need that kind of UX, you have two options:
* **Accept user keywords at any input.** Add a [Reply event](/editor/events/reply) that reacts to specific keywords (see the [user commands guide](/guides/user-commands)). The input still belongs to the current block, but the user can type commands like `help` or `restart` from anywhere.
* **Build a custom UI.** Use the [continueChat HTTP API](/api-reference/chat/continue-chat) to drive the conversation yourself and render whatever chat interface you want, including a persistent input. This is significantly more work than using the official embeds.
# Welcome 👋
Source: https://docs.typebot.com/get-started/introduction
Typebot is a fair source chatbot builder. It allows you to create conversational apps/forms (Lead qualification, Customer support, Product launch, User onboarding, AI chats), deploy it on your website or WhatsApp number, and collect results in real time.
This is the Typebot documentation. It's a great place to find most answers. Please use the search box to quickly find the answers you're looking for.
Learn how Typebot works and how to use it to build your first chatbot.
Explore the different ways you can deploy your bot.
Interested in creating a block or improve the app? Learn how to contribute.
Learn how to self-host Typebot on your own server.
# Creating a typebot
Source: https://docs.typebot.com/get-started/overview
The best way to understand the basic principles of Typebot is by watching this super quick "Creating a typebot" video:
# Integrate with external messaging apps via HTTP API
Source: https://docs.typebot.com/guides/external-messaging-apps
Typebot ships native integrations for the web and WhatsApp. For messaging platforms that don't have a dedicated integration (KakaoTalk, LINE, WeChat, Telegram, Viber, or any proprietary chat app), you can still drive a Typebot conversation by calling the HTTP API yourself.
The integration sits between the messaging app and Typebot: it receives each incoming message from the platform, forwards it to Typebot, and relays the bot reply back to the user.
## How it works
For each user, you need to persist one Typebot `sessionId` so the conversation stays stateful across messages.
Most messaging platforms (KakaoTalk, LINE, Telegram, etc.) let you register a webhook URL that is called whenever a user sends a message. Create an HTTP endpoint on your server to handle those calls.
If you don't have a `sessionId` for this user yet, call the [start chat endpoint](/api-reference/chat/start-chat):
```sh theme={null}
curl -X POST https://typebot.co/api/v1/typebots//startChat \
-H "Content-Type: application/json" \
-d '{}'
```
Store the returned `sessionId` next to the user's platform ID in your database.
For every following message from the same user, call [continueChat](/api-reference/chat/continue-chat) with the stored session:
```sh theme={null}
curl -X POST https://typebot.co/api/v1/sessions//continueChat \
-H "Content-Type: application/json" \
-d '{"message": "user reply here"}'
```
Both endpoints return a `messages` array describing what the bot wants to say (text bubbles, images, buttons, etc.). Map each message to the equivalent primitive on the target platform — for example a KakaoTalk text bubble, a LINE template message, or a Telegram inline keyboard.
If the response contains an `input`, present it to the user (buttons become quick replies, a text input just waits for the next message, etc.). When the user answers, loop back to the previous step.
## Things to keep in mind
* **Authentication.** Public endpoints (`/api/v1/typebots//startChat`) don't require a token. If you want to use the preview endpoint or any authenticated route, [generate an API token](/api-reference/authentication).
* **Session lifetime.** Sessions expire after a period of inactivity. Handle 404 errors from `continueChat` by starting a new session transparently.
* **Block compatibility.** Blocks that rely on the web embed (file upload UI, payment form, embedded videos...) don't have a 1:1 equivalent on most messaging apps. Keep the flow text-first when you target external platforms.
* **Rate limits.** Messaging platforms usually enforce strict rate limits. Queue outgoing messages if the bot sends several bubbles in a row.
## Related
* [Chat API reference](/api-reference/chat/start-chat)
* [continueChat reference](/api-reference/chat/continue-chat)
* [API authentication](/api-reference/authentication)
# How to create loops?
Source: https://docs.typebot.com/guides/how-to-create-loops
In this video, I demonstrate how to implement a dynamic loop to collect guest names for a restaurant reservation chatbot.
I walk through setting up the chatbot to request the number of guests, and then, using JavaScript, create a list based on this number.
I explain how to use the 'Shift' set variable value to iterate through this list, collecting and storing each guest's name.
Despite the lack of a specific loop block in the platform, I show how to create a loop-like behavior through custom code.
The video is timestamped, feel free to move forward and back 👌
# How to get help?
Source: https://docs.typebot.com/guides/how-to-get-help
Here is what you should do if you have an issue or even a question (this list is ordered from fastest to slowest resolution time):
1. Read this documentation. I do my best to keep it up to date and to cover all the possible issues and questions. Use the search bar to find what you are looking for.
2. You can ask for help or report your bug in the [Discord community](https://typebot.io/discord). Specifically in the `#help-and-questions` channel. I try to answer all the questions there daily. There is also a good chance that someone else has already asked the same question and you can find the answer there using the search bar.
3. Users subscribed to the `Starter` or `Pro` plan can directly reach out to me through the chat widget in the bottom right corner of the app.
# How to split AI message into multiple messages
Source: https://docs.typebot.com/guides/how-to-split-ai-messages-in-multi-blocks
# Add a subscriber to MailerLite
Source: https://docs.typebot.com/guides/mailer-lite
1. Add a step that collects the email and set it into a variable
2. Add a Webhook step
3. Configure the Webhook step with the following information:
For more info on what fields you can add: [https://developers.mailerlite.com/reference/create-a-subscriber](https://developers.mailerlite.com/reference/create-a-subscriber)
4. Replace "YOUR\_TOKEN" with your API key. It can be found here: [https://app.mailerlite.com/integrations/api/](https://app.mailerlite.com/integrations/api/)
5. Whenever the user enters his email it should add it to your subscribers' list on MailerLite
# Dynamic avatars
Source: https://docs.typebot.com/guides/multi-avatars
You can decide to change the host avatar dynamically so that your bot can display multiple avatars. Here is a simple example:
For this, head over to the "Theme" tab and set the host avatar to a variable URL:
Then you can set this variable to any URL in your flow so that the host avatar changes dynamically.
The first block defines all the avatars that can be displayed. The second block starts by setting the avatar to the wizard avatar. The final block starts by setting the swordsmith avatar.
# Enable RTL
Source: https://docs.typebot.com/guides/rtl
* Head over to the "Theme" tab
* Paste the following Custom CSS:
```css theme={null}
.typebot-container {
direction: rtl;
}
.typebot-avatar-container {
margin-right: 0;
margin-left: 0.5rem;
}
.guest-container {
margin-left: 0;
margin-right: 50px;
}
```
# How to add user commands (restart, help...)
Source: https://docs.typebot.com/guides/user-commands
A common pattern is letting the user type keywords like `restart`, `help`, or `menu` at any point in the conversation to trigger a specific behavior. Typebot does not ship a dedicated block for this, but you can build it with a [Reply event](/editor/events/reply) combined with [Jump](/editor/blocks/logic/jump) and [Return](/editor/blocks/logic/return) blocks.
## Reply event vs Command event
These two events are easy to confuse:
* **[Reply event](/editor/events/reply)** fires on every user reply (text, button click, etc.). Use it when the trigger is something the user types or selects inside the chat. This is what you want for `restart` or `help` keywords.
* **[Command event](/editor/events/command)** fires only when a command is sent programmatically via [`Typebot.sendCommand`](/deploy/web/html-javascript#commands) or the [continueChat API](/api-reference/chat/continue-chat). Use it to trigger flows from outside the conversation (a button on your page, an external webhook, etc.).
If you want the user to type a keyword to trigger behavior, use the Reply event.
## Implement a `restart` command
The goal: whenever the user replies with `restart`, the conversation jumps back to the very first block of the flow.
From the events sidebar, drag a Reply event onto the graph.
Inside the event subflow, add a [Condition block](/editor/blocks/logic/condition) that checks if the reply content equals `restart` (case-insensitive if you prefer).
On the `true` branch of the condition, add a [Jump block](/editor/blocks/logic/jump) pointing to the first block of your main flow.
On the `false` branch, add a [Return block](/editor/blocks/logic/return) so the conversation resumes normally when the user types anything else.
The Reply event fires **before** the reply is validated against the current input. This means the keyword works even if the user is currently on a number or email input.
## Implement a `help` command
Same pattern, but instead of jumping to the start of the flow, jump to a dedicated "Help" group that sends a few text bubbles explaining what the bot can do. End that group with a Return block so the user comes back to where they were.
## Handling multiple commands
You can chain several conditions inside a single Reply event subflow:
* `restart` → Jump to start
* `help` → Jump to help group
* `agent` → Jump to human handoff group
* anything else → Return
Keeping all your command routing inside one Reply event makes it easier to maintain than duplicating logic in every group.
# Forward UTM parameters to a typebot
Source: https://docs.typebot.com/guides/utm-in-results
The UTM parameter name should be listed in the Variables dropdown of your flow you can create it on any variable dropdown. Then, if your typebot is launched with the declared UTM parameter. It should appear in the Results tab.
Once you have saved the UTM values into variables like `utm_source` and `utm_value`. You can build a redirect URL in a [Redirect block](../editor/blocks/logic/redirect) with the same UTMs like this:
```
https://redirect-site.com?utm_source={{utm_source}}&utm_value={{utm_value}}
```
# Report Abuse
Source: https://docs.typebot.com/report-abuse
At Typebot, we uphold freedom of speech, but we also recognize our responsibility to keep our platform free from illegal content.
Here are some examples of content that is not allowed on Typebot:
1. Scams and Fraud: Content that engages in or promotes fraudulent schemes, scams, or con artistry designed to deceive and potentially divest users of their assets, personal information, or other valuables.
2. Phishing: Content or communications that unlawfully attempt to acquire sensitive information such as usernames, passwords, financial details, or other personal data by masquerading as a trustworthy entity in electronic communication.
3. Sexual Exploitation and Abuse: Any illegal material that involves or promotes sexual exploitation, such as child sexual abuse material, non-consensual pornography, or content connected to human trafficking.
4. Intellectual Property Violations: Content that infringes upon the copyright, patents, trademarks, or trade secrets of others without authorization in a manner that violates intellectual property laws.
5. Privacy Violations: Unlawfully sharing or distributing someone else's personal or confidential information without their explicit consent.
This list is not exhaustive. We continually monitor the platform and will take action on content that we determine to violate these restrictions in keeping with the law and our company policies, ensuring that Typebot remains a secure environment for all users.
Users are responsible for ensuring that the bot they publish, and their conduct on our platform adheres to relevant laws and our Terms of Service. For further information, please consult legal counsel or refer to local and international laws and regulations.
## Report
If you feel a typebot violates our Terms of Service, please report it to us by filling out the bot below.
# Analytics
Source: https://docs.typebot.com/results/analytics
The in-depth analytics help you identify user drop-off points and gain insights into user behavior so that you can incrementally improve your chat conversion rate.
## Definitions
The overview shows three top-level metrics:
* **Views**: every time a typebot is loaded by a visitor, even if they never interact with it.
* **Starts**: a result is counted as started as soon as the visitor submits at least one answer.
* **Completions**: a result is counted as completed when **all** of the following are true:
* The flow has reached an end (there is no further input waiting to be displayed).
* The visitor has submitted at least one answer (a session that ends before any input is answered is never counted as completed).
* There is no pending client-side Set Variable block whose code still needs to run in the browser and return a value to the engine.
Note that some other "waiting" states (a Custom embed message, or an Embed bubble with *Wait for event* enabled) do **not** prevent a result from being marked as completed: the result is closed as soon as the flow reaches an end with at least one answer, even if the embed has not yet emitted the awaited event.
The drop-off rate displayed next to each input block is the percentage of users who reached the block but never submitted an answer to it. It is only revealed on the Pro plan.
# Results
Source: https://docs.typebot.com/results/overview
Once your bot is [published](/editor/publish) you start to collect results from your users. You can see all the results in the `Results` tab of your bot.
You might be surprised to see partially filled results. This is normal and
expected. Your typebot collects the answers as soon as they are filled by the
user, even if the user doesn't complete the whole conversation. This is useful
to understand where users are dropping off and to improve your bot. This is
one of Typebot's greatest features.
## More options menu
## Time filter
By default, results from the last 7 days are displayed. You can change this by clicking on the date filter button:
### Export all results to a CSV file
You can export all results to a CSV file. This will download a CSV file with all the results from the current bot.
The `Include deleted blocks` option, if enabled, will include answers from blocks that doesn't exist any more (was part of a previous version of your bot).
### Re-arrange and hide specific columns
To make your result table more readable, you can re-arrange and hide specific columns.
## Transcript
You can see the transcript of a result by expanding the result row, clicking on the `Open` button when hovering the first row cell.
## Logs
Typebot does not expose a global activity feed. Logs are attached to individual results, so they live inside the `Results` table.
To see what happened during a conversation (including integration errors like Send email, Google Sheets, or HTTP request), open a specific result and look at the logs column. Each row has a "See logs" button:
Logs include integration outputs, errors, and warnings for that specific conversation. If an integration silently fails, this is where to look first.
# Breaking changes
Source: https://docs.typebot.com/self-hosting/breaking-changes
This lists all the breaking changes introduced in each version of Typebot.
Make sure to check all the intermediate versions as well. For example, if you are on **v2.21** and would like to upgrade to **v2.29**, you should apply all the breaking changes from **v2.21** to **v2.29**.
## v3.6
Existing chat sessions will crash if you come from v3.4 or below as we deleted a deprecated prop in session state. Make sure to first upgrade to v3.5, let all the ongoing chat sessions end and then upgrade to v3.6.
## v3.5
`workspaceId` optionnality was removed from chatSession state schema. If you have active chat sessions, make sure to first upgrade to v3.4 and wait for a few days for the incremental migration is done.
## v3.0
### Google variables renamed
`GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `NEXT_PUBLIC_GOOGLE_API_KEY` have been removed in favor of:
* Auth: `GOOGLE_AUTH_CLIENT_ID`, `GOOGLE_AUTH_CLIENT_SECRET`
* Sheets: `GOOGLE_SHEETS_CLIENT_ID`, `GOOGLE_SHEETS_CLIENT_SECRET`, `NEXT_PUBLIC_GOOGLE_SHEETS_API_KEY`
* Fonts: `NEXT_PUBLIC_GOOGLE_FONTS_API_KEY`
It allows for more granular control over the Google APIs you are using. Instead of enabling all of them.
If you still want to use the same keys for all Google APIs, you just have to set the same value for all of them.
### New license
The license was changed from AGPLv3 to FSL. It means that you can't fork the project to commercialize a Typebot competitor anymore. See the new requirements [here](./get-started).
### Migrated from pnpm to bun
Typebot is now using bun instead of pnpm as a package manager. Which means practically all deployments instructions need to be updated to now use bun.
# Configuration
Source: https://docs.typebot.com/self-hosting/configuration
If you're self-hosting Typebot, [sponsoring
me](https://github.com/sponsors/baptisteArno) is a great way to give back to
the community and to contribute to the long-term sustainability of the
project. It also comes with some perks like priority support and private
workshops. ❤️
Parameters marked with \* are required.
## General
| Parameter | Default | Description |
| ------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DATABASE\_URL \* | | The database URL |
| ENCRYPTION\_SECRET \* | | A 256-bit key used to encrypt sensitive data. It is strongly recommended to [generate](./deploy/docker#2-add-the-required-configuration) a new one. The secret should be the same between builder and viewer. |
| NEXTAUTH\_URL \* | | The builder base URL. Should be the publicly accessible URL (i.e. `https://typebot.domain.com`) |
| NEXT\_PUBLIC\_VIEWER\_URL \* | | The viewer base URL. Should be the publicly accessible URL (i.e. `https://bot.domain.com`) |
| ADMIN\_EMAIL | | The email that will get an `UNLIMITED` plan on user creation. The associated user will be able to bypass database rules. You can provide multiple emails separated by a comma without spaces. |
| DEFAULT\_WORKSPACE\_PLAN | FREE | Default workspace plan on user creation or when a user creates a new workspace. Possible values are `FREE`, `STARTER`, `PRO`, `LIFETIME`, `UNLIMITED`. The default plan for admin user is `UNLIMITED` |
| DISABLE\_SIGNUP | false | Disable new user sign ups. Invited users are still able to sign up. |
| NEXT\_PUBLIC\_ONBOARDING\_TYPEBOT\_ID | | Typebot ID used for the onboarding. Onboarding page is skipped if not provided. |
| TYPEBOT\_DEBUG | false | If enabled, the server will print valuable logs to debug config issues. |
| NEXT\_PUBLIC\_BOT\_FILE\_UPLOAD\_MAX\_SIZE | | Limits the size of each file that can be uploaded in the bots (i.e. Set `10` to limit the file upload to 10MB) |
| CHAT\_API\_TIMEOUT | | The chat API execution timeout (in ms). It limits the chat API exection time. Useful to avoid getting stuck into an unwanted infinite loop. Note that it does not apply to known long-running blocks like OpenAI or else. |
## Email (Auth, notifications)
Used for sending email notifications and authentication
| Parameter | Default | Description |
| ------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SMTP\_USERNAME | | SMTP username |
| SMTP\_PASSWORD | | SMTP password |
| SMTP\_HOST | | SMTP host. (i.e. `smtp.host.com`) |
| SMTP\_PORT | 25 | SMTP port |
| NEXT\_PUBLIC\_SMTP\_FROM | | From name and email (i.e. `'Typebot Notifications' `) |
| SMTP\_SECURE | false | If true the connection will use TLS when connecting to server. If false (the default) then TLS is used if server supports the STARTTLS extension. In most cases set this value to true if you are connecting to port 465. For port 587 or 25 keep it false |
| SMTP\_IGNORE\_TLS | undefined | If true and SMTP\_SECURE is false then TLS is not used while connecting to server even if server supports STARTTLS extension. |
| SMTP\_AUTH\_DISABLED | false | To disable the authentication by email but still use the provided config for notifications |
## Google Auth
1. Head over the Credentials tab: [https://console.developers.google.com/apis/credentials](https://console.developers.google.com/apis/credentials)
2. Create a OAuth client ID. This will be your `GOOGLE_AUTH_CLIENT_ID` and `GOOGLE_AUTH_CLIENT_SECRET`
Make sure to set the following scopes: `userinfo.email`
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path:
* For production:
* https\://\/api/auth/callback/google
* For development:
* [http://localhost:3000/api/auth/callback/google](http://localhost:3000/api/auth/callback/google)
| Parameter | Default | Description |
| ---------------------------- | ------- | --------------------------------------------- |
| GOOGLE\_AUTH\_CLIENT\_ID | | The Client ID from the Google API Console |
| GOOGLE\_AUTH\_CLIENT\_SECRET | | The Client secret from the Google API Console |
## Google Sheets
1. Enable the following APIs in the Google Cloud Console: Google Sheets API, Google Picker API
2. Head over the Credentials tab: [https://console.developers.google.com/apis/credentials](https://console.developers.google.com/apis/credentials)
3. Create an API key. This will be your `NEXT_PUBLIC_GOOGLE_SHEETS_API_KEY`
4. Create a OAuth client ID. This will be your `GOOGLE_SHEETS_CLIENT_ID` and `GOOGLE_SHEETS_CLIENT_SECRET`
Make sure to set the following scopes located in your OAuth Consent Screen: `spreadsheets`, `drive.file`
[https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes)
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path:
* For production:
* https\://\/api/credentials/google-sheets/callback
* For development:
* [http://localhost:3000/api/credentials/google-sheets/callback](http://localhost:3000/api/credentials/google-sheets/callback)
5. To avoid having to always reconnect a Google Sheets credentials every 7 days, you need to promote your OAuth client to production ([https://developers.google.com/nest/device-access/reference/errors/authorization#refresh\_token\_keeps\_expiring](https://developers.google.com/nest/device-access/reference/errors/authorization#refresh_token_keeps_expiring))
| Parameter | Default | Description |
| -------------------------------------- | ------- | --------------------------------------------- |
| GOOGLE\_SHEETS\_CLIENT\_ID | | The Client ID from the Google API Console |
| GOOGLE\_SHEETS\_CLIENT\_SECRET | | The Client secret from the Google API Console |
| NEXT\_PUBLIC\_GOOGLE\_SHEETS\_API\_KEY | | The API Key from the Google API Console |
## Gmail
1. Enable the following APIs in the Google Cloud Console: Google Sheets API, Google Picker API
2. Head over the Credentials tab: [https://console.developers.google.com/apis/credentials](https://console.developers.google.com/apis/credentials)
3. Create a OAuth client ID. This will be your `GMAIL_CLIENT_ID` and `GMAIL_CLIENT_SECRET`
Make sure to set the following scopes located in your OAuth Consent Screen: `gmail.send`, `gmail.labels`, `userinfo.profile`, `userinfo.email`
[https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes)
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path:
* For production:
* https\://\/oauth/redirect
* For development:
* [http://localhost:3000/oauth/redirect](http://localhost:3000/oauth/redirect)
4. To avoid having to always reconnect credentials every 7 days, you need to promote your OAuth client to production ([https://developers.google.com/nest/device-access/reference/errors/authorization#refresh\_token\_keeps\_expiring](https://developers.google.com/nest/device-access/reference/errors/authorization#refresh_token_keeps_expiring))
| Parameter | Default | Description |
| --------------------- | ------- | --------------------------------------------- |
| GMAIL\_CLIENT\_ID | | The Client ID from the Google API Console |
| GMAIL\_CLIENT\_SECRET | | The Client secret from the Google API Console |
## Google Fonts
Used authentication in the builder and for the Google Sheets integration step.
1. Enable the following API in the Google Cloud Console: Web Fonts Developer API
2. Head over the Credentials tab: [https://console.developers.google.com/apis/credentials](https://console.developers.google.com/apis/credentials)
3. Create an API key with access to the Web Fonts Developer API. This will be your `NEXT_PUBLIC_GOOGLE_FONTS_API_KEY`
| Parameter | Default | Description |
| ------------------------------------- | ------- | --------------------------------------- |
| NEXT\_PUBLIC\_GOOGLE\_FONTS\_API\_KEY | | The API Key from the Google API Console |
## GitHub (Auth)
Used for authenticating with GitHub. By default, it uses the credentials of a Typebot-dev app.
You can create your own GitHub OAuth app [here](https://github.com/settings/developers). The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/github`
| Parameter | Default | Description |
| ---------------------- | ------- | --------------------------------------------------------------------------- |
| GITHUB\_CLIENT\_ID | | Application client ID. Also used to check if it is enabled in the front-end |
| GITHUB\_CLIENT\_SECRET | | Application secret |
## GitLab (Auth)
Used for authenticating with GitLab.
Follow the official GitLab guide for creating OAuth2 applications [here](https://docs.gitlab.com/ee/integration/oauth_provider.html).
The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/gitlab`
| Parameter | Default | Description |
| ------------------------ | ---------------------------------------- | ------------------------------------------------------------------------------------ |
| GITLAB\_CLIENT\_ID | | Application client ID. Also used to check if it is enabled in the front-end |
| GITLAB\_CLIENT\_SECRET | | Application secret |
| GITLAB\_BASE\_URL | [https://gitlab.com](https://gitlab.com) | Base URL of the GitLab instance |
| GITLAB\_REQUIRED\_GROUPS | | Comma-separated list of groups the user has to be a direct member of, e.g. `foo,bar` |
| GITLAB\_NAME | GitLab | Name of the GitLab instance, used for the SSO Login Button |
## Facebook (Auth)
You can create your own Facebook OAuth app [here](https://developers.facebook.com/apps/create/).
The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/facebook`
| Parameter | Default | Description |
| ------------------------ | ------- | --------------------------------------------------------------------------- |
| FACEBOOK\_CLIENT\_ID | | Application client ID. Also used to check if it is enabled in the front-end |
| FACEBOOK\_CLIENT\_SECRET | | Application secret |
## Azure AD (Auth)
If you are using [Azure Active Directory](https://azure.microsoft.com/en-us/services/active-directory/) for the authentication you can set the following environment variables.
The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/azure-ad`
| Parameter | Default | Description |
| ------------------------- | ------- | ------------------------------------------------------------- |
| AZURE\_AD\_CLIENT\_ID | | Application client ID |
| AZURE\_AD\_CLIENT\_SECRET | | Application client secret. Can be obtained from Azure Portal. |
| AZURE\_AD\_TENANT\_ID | | Azure Tenant ID |
## Keycloak (Auth)
Used for authenticating with Keycloak.
Follow the official Keycloak guide for creating OAuth2 applications [here](https://www.keycloak.org/).
| Parameter | Default | Description |
| ------------------------ | ------- | --------------------------------- |
| KEYCLOAK\_CLIENT\_ID | | Application client ID. |
| KEYCLOAK\_CLIENT\_SECRET | | Application secret |
| KEYCLOAK\_REALM | | Your Keycloak Realm |
| KEYCLOAK\_BASE\_URL | | Base URL of the Keycloak instance |
## Custom OAuth Provider (Auth)
Your provider needs to support the [OpenID Connect](https://openid.net/connect/) standards.
| Parameter | Default | Description |
| --------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------------- |
| CUSTOM\_OAUTH\_CLIENT\_ID \* | | OAuth client ID. |
| CUSTOM\_OAUTH\_CLIENT\_SECRET \* | | OAuth client secret. |
| CUSTOM\_OAUTH\_ISSUER \* | | OAuth issuer URL (i.e. `https://auth.domain.com/openid`) |
| CUSTOM\_OAUTH\_NAME | Custom OAuth | Provider name. Will be displayed in the sign in form. |
| CUSTOM\_OAUTH\_WELL\_KNOWN\_URL | `CUSTOM_OAUTH_ISSUER`/.well-known/openid-configuration | Provider .well-known URL |
| CUSTOM\_OAUTH\_USER\_ID\_PATH | id | Used to map the id from the user info object |
| CUSTOM\_OAUTH\_USER\_NAME\_PATH | name | Used to map the name from the user info object |
| CUSTOM\_OAUTH\_USER\_EMAIL\_PATH | email | Used to map the email from the user info object |
| CUSTOM\_OAUTH\_USER\_IMAGE\_PATH | image | Used to map the image from the user info object |
| CUSTOM\_OAUTH\_SCOPE | openid profile email | OAuth scope |
For `*_PATH` parameters, you can use dot notation to access nested properties (i.e. `account.name`).
The Authorization callback URL should be: `$NEXTAUTH_URL/api/auth/callback/custom-oauth`
## S3 Storage (Media uploads)
Used for uploading images, videos, etc... It can be any S3 compatible object storage service (Minio, Digital Oceans Space, AWS S3...)
| Parameter | Default | Description |
| -------------------------- | ------- | ---------------------------------------------------------------------------------- |
| S3\_ACCESS\_KEY | | S3 access key. Also used to check if upload feature is enabled |
| S3\_SECRET\_KEY | | S3 secret key. |
| S3\_BUCKET | typebot | Name of the bucket where assets will be uploaded in. |
| S3\_PORT | | S3 Host port number |
| S3\_ENDPOINT | | S3 endpoint (i.e. `s3.domain.com`). |
| S3\_SSL | true | Use SSL when establishing the connection. |
| S3\_REGION | | S3 region. |
| S3\_PUBLIC\_CUSTOM\_DOMAIN | | If the final URL that is used to read public files is different from `S3_ENDPOINT` |
Note that for AWS S3, your endpoint is usually: `s3..amazonaws.com`
In order to function properly, your S3 bucket must be configured. Make sure to read through the [S3 configuration](./guides/s3) doc.
## Giphy (GIF picker)
Used to search for GIF. You can create a Giphy app [here](https://developers.giphy.com/dashboard/)
| Parameter | Default | Description |
| ----------------------------- | ------- | ------------- |
| NEXT\_PUBLIC\_GIPHY\_API\_KEY | | Giphy API key |
## Unsplash (image picker)
Used to search for images. You can create an Unsplash app [here](https://unsplash.com/developers)
| Parameter | Default | Description |
| ----------------------------------- | ------- | ----------------- |
| NEXT\_PUBLIC\_UNSPLASH\_APP\_NAME | | Unsplash App name |
| NEXT\_PUBLIC\_UNSPLASH\_ACCESS\_KEY | | Unsplash API key |
## Pexels (video picker)
Used to search for videos. You can create a Pexels app [here](https://www.pexels.com/api/key/)
| Parameter | Default | Description |
| ------------------------------ | ------- | -------------- |
| NEXT\_PUBLIC\_PEXELS\_API\_KEY | | Pexels API key |
## Tolgee (i18n contribution dev tool)
If you'd like to join contribute to Typebot's translation join the [Discord
server](https://discord.gg/xjyQczWAXV) and ask for an access to Tolgee in the
[#contributors
channel](https://discord.com/channels/1155799591220953138/1155883114455900190).
Set up these environment variables to enable [Tolgee dev tool](https://tolgee.io/features/dev-tools).
| Parameter | Default | Description |
| ------------------------------ | -------------------------------------------------------------------------------- | ----------------------- |
| NEXT\_PUBLIC\_TOLGEE\_API\_KEY | | Your Tolgee API key |
| NEXT\_PUBLIC\_TOLGEE\_API\_URL | [https://tolgee.server.baptistearno.com](https://tolgee.server.baptistearno.com) | The Tolgee API base URL |
## WhatsApp (Preview)
In order to be able to test your bot on WhatsApp from the Preview drawer, you need to set up a WhatsApp business app.
## 1. [Create a WhatsApp Meta app](../deploy/whatsapp/create-meta-app)
## 2. Get the App Secret and System User token
1. Go to your app's `App settings > Basic` page and copy the App Secret. This will be used as `WHATSAPP_PREVIEW_APP_SECRET` in your builder configuration.
2. Go to your [System users page](https://business.facebook.com/settings/system-users) and create a new system user that has access to the related.
* Token expiration: `Never`
* Available Permissions: `whatsapp_business_messaging`, `whatsapp_business_management`
3. The generated token will be used as `META_SYSTEM_USER_TOKEN` in your viewer configuration.
4. Click on `Add assets`. Under `Apps`, look for your app, select it and check `Manage app`
## 3. Get the phone number ID
1. Go to your WhatsApp Dev Console
2. Add your phone number by clicking on the `Add phone number` button.
3. Select the newly created phone number in the `From` dropdown list and you will see right below the associated `Phone number ID` This will be used as `WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID` in your viewer configuration.
## 4. Set up the webhook
1. Head over to `Quickstart > Configuration`. Edit the webhook URL to `$NEXTAUTH_URL/api/v1/whatsapp/preview/webhook`. Set the Verify token to `$ENCRYPTION_SECRET` and click on `Verify and save`.
2. Add the `messages` webhook field.
## 5. Set up the message template
1. Head over to `Messaging > Message Templates` and click on `Create Template`
2. Select the `Utility` category
3. Give it a name that corresponds to your `WHATSAPP_PREVIEW_TEMPLATE_NAME` configuration.
4. Select the language that corresponds to your `WHATSAPP_PREVIEW_TEMPLATE_LANG` configuration.
5. You can format it as you'd like. The user will just have to send a message to start the preview.
| Parameter | Default | Description |
| ------------------------------------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| META\_SYSTEM\_USER\_TOKEN | | The system user token used to send WhatsApp messages |
| WHATSAPP\_PREVIEW\_FROM\_PHONE\_NUMBER\_ID | | The phone number ID from which the message will be sent |
| WHATSAPP\_PREVIEW\_APP\_SECRET | | The Meta app secret used to verify preview webhook signatures |
| WHATSAPP\_PREVIEW\_TEMPLATE\_NAME | | The preview start template message name |
| WHATSAPP\_PREVIEW\_TEMPLATE\_LANG | en\_US | The preview start template message name |
| WHATSAPP\_CLOUD\_API\_URL | [https://graph.facebook.com](https://graph.facebook.com) | The WhatsApp Cloud API base URL |
| WHATSAPP\_INTERACTIVE\_GROUP\_SIZE | 3 | The array size of items to send to API on choice input. You can't choose a number higher than 3 if you are using the official cloud API URL. |
## Redis
In Typebot, Redis is optional and is used to:
* Rate limit the sign in requests based on user IP
* Enable multiple media upload on WhatsApp
| Parameter | Default | Description |
| ---------- | ------- | -------------------------------------------------------------------- |
| REDIS\_URL | | The database URL. i.e. `redis://:@:` |
## PartyKit
PartyKit is optional and is used to make the webhook block work. The PartyKit configuration is located in `packages/partykit` folder. You can deploy the server into production using `bun deploy`. You can find more information about PartyKit deployment in their [official documentation](https://docs.partykit.io/guides/deploying-your-partykit-server/).
| Parameter | Default | Description |
| ---------------------------- | ------- | ----------------------------------------- |
| NEXT\_PUBLIC\_PARTYKIT\_HOST | | PartyKit host. i.e. `partykit.typebot.io` |
## Others
The related environment variables are listed here but you are probably not interested in these if you self-host Typebot.
| Parameter | Default | Description |
| ------------------------------------------- | ------- | ----------------------------------------------- |
| VERCEL\_TOKEN | | Vercel API token |
| NEXT\_PUBLIC\_VERCEL\_VIEWER\_PROJECT\_NAME | | The name of the viewer project in Vercel |
| VERCEL\_TEAM\_ID | | Vercel team ID that contains the viewer project |
| Parameter | Default | Description |
| --------------------------- | ------- | ------------------------------------------------------- |
| MESSAGE\_WEBHOOK\_URL | | Webhook URL called to receive important system messages |
| USER\_CREATED\_WEBHOOK\_URL | | Webhook URL called whenever a new user is created |
| Parameter | Default | Description |
| ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------- |
| OTEL\_EXPORTER\_OTLP\_ENDPOINT | | OTLP HTTP endpoint used to export telemetry. Typebot sends traces to `/v1/traces` and logs to `/v1/logs`. |
| OTEL\_EXPORTER\_OTLP\_HEADERS | | Comma-separated OTLP headers passed to the exporter. Format: `key=value,another=value`. |
| OTEL\_EXPORTER\_OTLP\_SIGNALS | `traces` | Which signals to export. Possible values are `traces`, `logs`, `both`. Set `logs` if you only want Effect logs. |
| Parameter | Default | Description |
| --------------------------- | ------------------------------------------------ | ------------------------ |
| NEXT\_PUBLIC\_POSTHOG\_KEY | | PostHog API Key |
| POSTHOG\_API\_HOST | [https://eu.posthog.com](https://eu.posthog.com) | PostHog API Host |
| POSTHOG\_PERSONAL\_API\_KEY | | PostHog personal API Key |
| POSTHOG\_PROJECT\_ID | | PostHog project ID |
| Parameter | Default | Description |
| ----------------------------------- | ---------------------------------------- | ----------- |
| NEXT\_PUBLIC\_VIEWER\_404\_TITLE | 404 | |
| NEXT\_PUBLIC\_VIEWER\_404\_SUBTITLE | The bot you're looking for doesn't exist | |
# Alibaba Cloud
Source: https://docs.typebot.com/self-hosting/deploy/alibaba-cloud
How to deploy Typebot on Alibaba Cloud
The easiest way to get started with Typebot is with [the official managed
service in the Cloud](https://app.typebot.io). You'll have high availability,
backups, security, and maintenance all managed for you by me, Baptiste,
Typebot's founder. The cloud version can save a substantial amount of
developer time and resources. For most sites this ends up being the best value
option and the revenue goes to funding the maintenance and further development
of Typebot. So you'll be supporting fair source software and getting a great
service!
Additionally, Alibaba Cloud offers a streamlined setup process using Docker Compose for quickly launching the entire Typebot application.
It automatically creates OAuth credentials for Alibaba Cloud and configures a public IP for your application.
Throughout the deployment process, you'll only need to provide a few simple parameters to start using Typebot seamlessly.
Furthermore, if you already have a GitHub OAuth Client created, the deployment process also supports enabling GitHub OAuth login directly.
## Requirements
You need an Alibaba Cloud account, which you can register for on [Alibaba Cloud](https://alibabacloud.com/).
## Getting Started
* Builder is the application where you'll create your flows.
* Viewer is the bot interface your users will interact with.
### One-click to deploy the builder and viewer
[![][deploy-button-image]][deploy-link]
1. Select parameters for the type of ECS to deploy
2. Choose to create a new dedicated network or directly use an existing dedicated network based on your needs.
3. Alibaba Cloud automatically creates an OAuth client for Alibaba Cloud services. If you choose to use GitHub OAuth login (optional), you can enter your GitHub Client ID and Secret.
4. Then click 'Create Now' and wait for the service instance to be deployed. You can now use the build page exposed by the service instance to create and interact with your chatbot.
[deploy-button-image]: https://service-info-public.oss-cn-hangzhou.aliyuncs.com/computenest-en.svg
[deploy-link]: https://computenest.console.aliyun.com/service/instance/create/default?type=user&ServiceName=Typebot%E7%A4%BE%E5%8C%BA%E7%89%88
# Docker
Source: https://docs.typebot.com/self-hosting/deploy/docker
The easiest way to get started with Typebot is with [the official managed
service in the Cloud](https://app.typebot.io). You'll have high availability,
backups, security, and maintenance all managed for you by me, Baptiste,
Typebot's founder. The cloud version can save a substantial amount of
developer time and resources. For most sites this ends up being the best value
option and the revenue goes to funding the maintenance and further development
of Typebot. So you'll be supporting fair source software and getting a great
service!
## Requirements
You need a server with Docker installed. If your server doesn't come with Docker pre-installed, you can follow [their docs](https://docs.docker.com/engine/install/#server) to install it.
## Installation
### 1. Download the compose file
On your server, download the latest `docker-compose.yml` and the starter `.env` file:
```sh theme={null}
wget https://raw.githubusercontent.com/baptisteArno/typebot.io/latest/docker-compose.yml
wget https://raw.githubusercontent.com/baptisteArno/typebot.io/latest/.env.example -O .env
```
### 2. Add the required configuration
1. You'll first need a random 32-character secret key which will be used to encrypt sensitive data. Here is a simple way to generate one:
```sh theme={null}
openssl rand -base64 24 | tr -d '\n' ; echo
```
2. Fill the `.env` file with your values.
3. Configure at least one authentication provider (Email, Google, GitHub, Facebook or GitLab). More info here: [Configuration](../configuration).
By default the compose file will pull the latest stable Typebot images: `baptistearno/typebot-builder:latest` and `baptistearno/typebot-viewer:latest`. You can decide to replace `latest` with a specific version. You can find all the existing tags [here](https://hub.docker.com/r/baptistearno/typebot-builder/tags)
### 3. Start the server
Once you've added your configuration to the compose file, you're ready to start up the server:
```sh theme={null}
docker-compose up -d
```
When you run this command, by default, it does the following:
* Create a database
* Run the migrations
* Start the builder on port 8080
* Start the viewer on port 8081
* All Typebot's data is stored in the `.typebot` folder in the current directory
You can now navigate to `http://typebot.domain.com:8080` and see the login screen. Login with the admin email to have access to a Team plan workspace automatically.
Typebot server itself does not perform SSL termination. It only runs on unencrypted HTTP. If you want to run on HTTPS you also need to set up a reverse proxy in front of the server. See below instructions.
### Update Typebot
Typebot is updated regularly, but it is up to you to apply these updates on your server. By virtue of using Docker, these updates are safe and easy to apply.
1. Pull the new images:
```sh theme={null}
docker-compose pull typebot-builder
docker-compose pull typebot-viewer
```
Alternatively, you can pull specific versions:
```sh theme={null}
docker-compose pull typebot-builder:3.4.2
docker-compose pull typebot-viewer:3.4.2
```
2. Stop the server:
```sh theme={null}
docker-compose down
```
3. Start the server (with the new images):
```sh theme={null}
docker-compose up -d
```
The self-hosted version is somewhat of a LTS, only getting the changes (\~ once per month) after they have been battle tested on the cloud version. If you want features as soon as they are available, consider becoming a [cloud user](https://app.typebot.io).
## Optional extras
### Reverse proxy
By default, Typebot runs on unencrypted HTTP on ports 8080 for the builder and 8081 for the viewer. We recommend running it on HTTPS behind a reverse proxy of some sort. You may or may not already be running a reverse proxy on your host, let's look at both options:
#### No existing reverse proxy
If your DNS is managed by a service that offers a proxy option with automatic SSL management, feel free to use that. For example, you could use Cloudflare as a reverse proxy in front of Typebot.
Alternatively, you can run your Caddy server as a reverse proxy. This way your SSL certificate will be stored on the host machine and managed by Let's Encrypt. The Caddy server will expose port 443, terminate SSL traffic and proxy the requests to your Typebot server.
Here is an example of a docker-compose file using Caddy as a reverse proxy:
```yml theme={null}
services:
caddy-gen:
container_name: caddy-gen
image: 'wemakeservices/caddy-gen:latest'
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- {$PWD}/.typebot/caddy-certificates:/data/caddy
ports:
- '80:80'
- '443:443'
depends_on:
- typebot-builder
- typebot-viewer
typebot-builder:
labels:
virtual.host: 'typebot.domain.com' # change to your domain name
virtual.port: '3000'
virtual.tls-email: 'admin@example.com' # change to your email
typebot-viewer:
labels:
virtual.host: 'bot.domain.com' # change to your domain name
virtual.port: '3000'
virtual.tls-email: 'admin@example.com' # change to your email
# Necessary to enable message streaming
virtual.proxy.directives: |
flush_interval -1
```
This config requires you to add the following DNS entry:
```
typebot IN A
bot IN A
```
You can merge this compose file with the first one. Make sure that `NEXTAUTH_URL` is set to `https://typebot.domain.com` and `NEXT_PUBLIC_VIEWER_URL` is set to `https://bot.domain.com`.
When running the compose file, it should automatically enable SSL on your server and you should be able to navigate to:
* `https://typebot.domain.com` for the builder
* `https://bot.domain.com` for the viewer
#### Existing reverse proxy
If you're already running a reverse proxy, the most important things to note are:
1. Configure the virtual hosts to match the `NEXTAUTH_URL` and `NEXT_PUBLIC_VIEWER_URL` in your `docker-compose` configuration.
2. Proxy the traffic to `127.0.0.1:8080` or `{ip-address}:8080` and to `127.0.0.1:8081` or `{ip-address}:8081` if running on a remote machine
### SMTP
I highly recommend using an external SMTP service. There are tons of options out there, including [SendInBlue](https://www.sendinblue.com/), [Mailgun](https://www.mailgun.com/) and [SendGrid](https://sendgrid.com/). It will avoid severe headaches 😅. Then, you will only need to add the required [SMTP configuration variables](/self-hosting/configuration#email-auth-notifications).
If, however, you don't want to, you can instantiate an SMTP server in the docker-compose file.
```yml theme={null}
services:
mail:
image: bytemark/smtp
restart: always
```
And add the following variables to your `.env` file:
```
SMTP_HOST=mail
NEXT_PUBLIC_SMTP_FROM=notifications@typebot.domain.com
```
You will probably need to make sure that `typebot.domain.com` has a valid SPF record and that your server IP has a rDNS set up.
You can merge this compose file with the main one.
### S3 storage
If you don't already have an S3 storage available, you could include it in your docker-compose file:
```yml theme={null}
services:
minio:
image: minio/minio
command: server /data
ports:
- "9000:9000"
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD: minio123
volumes:
- s3-data:/data
# This service just makes sure a bucket with the right policies is created
createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 10;
/usr/bin/mc alias set minio http://minio:9000 minio minio123;
/usr/bin/mc mb --ignore-existing minio/typebot;
/usr/bin/mc anonymous set public minio/typebot/public;
exit 0;
"
volumes:
s3-data:
```
And add the following variables to your `.env` file:
```
S3_ACCESS_KEY=minio
S3_SECRET_KEY=minio123
S3_BUCKET=typebot
S3_ENDPOINT=storage.domain.com
```
This config requires you to add the following DNS entry:
```
storage IN A
```
You can merge this compose file with the main one.
## Config example with all the extras
Here is a config example that spins up Typebot with HTTPS, SMTP and S3 storage.
```yml theme={null}
services:
caddy-gen:
image: 'wemakeservices/caddy-gen:latest'
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- {$PWD}/.typebot/caddy-certificates:/data/caddy
ports:
- '80:80'
- '443:443'
depends_on:
- typebot-builder
- typebot-viewer
typebot-db:
image: postgres:16
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=typebot
- POSTGRES_PASSWORD=typebot
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
typebot-builder:
labels:
virtual.host: 'typebot.domain.com' # change to your domain
virtual.port: '3000'
virtual.tls-email: 'admin@example.com' # change to your email
image: baptistearno/typebot-builder:latest
depends_on:
typebot-db:
condition: service_healthy
restart: always
extra_hosts:
- 'host.docker.internal:host-gateway'
# See https://docs.typebot.io/self-hosting/configuration for more configuration options
env_file:
- .env
typebot-viewer:
labels:
virtual.host: 'bot.domain.com' # change to your domain
virtual.port: '3000'
virtual.tls-email: 'admin@example.com' # change to your email
# Necessary to enable message streaming
virtual.proxy.directives: |
flush_interval -1
image: baptistearno/typebot-viewer:latest
depends_on:
typebot-db:
condition: service_healthy
restart: always
# See https://docs.typebot.io/self-hosting/configuration for more configuration options
env_file:
- .env
mail:
image: bytemark/smtp
restart: always
minio:
labels:
virtual.host: 'storage.domain.com' # change to your domain
virtual.port: '9000'
virtual.tls-email: 'admin@example.com' # change to your email
image: minio/minio
command: server /data
ports:
- '9000:9000'
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD: minio123
volumes:
- s3-data:/data
# This service just make sure a bucket with the right policies is created
createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 10;
/usr/bin/mc alias set minio http://minio:9000 minio minio123;
/usr/bin/mc mb --ignore-existing minio/typebot;
/usr/bin/mc anonymous set public minio/typebot/public;
exit 0;
"
volumes:
db-data:
s3-data:
```
## Build your own images
To build your own builder Docker image
```sh theme={null}
docker build -t typebot-builder --build-arg SCOPE=builder .
```
To build your own viewer Docker image
```sh theme={null}
docker build -t typebot-viewer --build-arg SCOPE=viewer .
```
## Troubleshooting
### Avoiding network issues when migrating in Portainer
If you migrate a Typebot stack between Portainer instances, hostname resolution may fail, causing `typebot-viewer` to be unable to connect to `typebot-db`.
Before deploying the stack in Portainer, ensure the network is **explicitly defined as attachable** in `docker-compose.yml`:
```yml theme={null}
networks:
typebot_network:
driver: bridge
attachable: true
services:
typebot-db:
...
networks:
- typebot_network
typebot-builder:
...
networks:
- typebot_network
typebot-viewer:
...
networks:
- typebot_network
```
When deploying the stack, Portainer will automatically create the network with the correct settings. This prevents hostname resolution issues after migration.
If you're self-hosting Typebot, [sponsoring
me](https://github.com/sponsors/baptisteArno) is a great way to give back to
the community and to contribute to the long-term sustainability of the
project. It also comes with some perks like priority support and private
workshops. ❤️
This doc has been inspired by [Plausible docs](https://plausible.io/docs).
They have a similar self-hosting solutions, and their documentation is 🔥.
# Manual
Source: https://docs.typebot.com/self-hosting/deploy/manual
This doc is for deploying Typebot on a server manually. If you're looking for
running Typebot locally, for development purposes, check out the [local
installation guide](../../contribute/guides/local-installation).
The easiest way to get started with Typebot is with [the official managed
service in the Cloud](https://app.typebot.io). You'll have high availability,
backups, security, and maintenance all managed for you by me, Baptiste,
Typebot's founder. The cloud version can save a substantial amount of
developer time and resources. For most sites this ends up being the best value
option and the revenue goes to funding the maintenance and further development
of Typebot. So you'll be supporting fair source software and getting a great
service!
## Requirements
* A Postgres database hosted somewhere. For production, [Neon](https://typebot.com/neon) is my provider of choice. This is not an affiliate link; it is simply the provider I use and recommend for a production database. You can also use any compatible Postgres provider or host Postgres yourself.
* A server with Node.js 24.x, [bun](https://bun.sh/docs/installation), Nginx, and PM2 installed.
* Experience in deploying Next.js applications with PM2. Check out [this guide](https://www.coderrocketfuel.com/article/how-to-deploy-a-next-js-website-to-a-digital-ocean-server/) for more information.
## Getting Started
1. Fork/clone the repository and checkout the latest stable version.
```sh theme={null}
git clone git@github.com:/typebot.io.git
cd typebot.io
git checkout latest
```
2. Setup environment variables by copying the example files and following the [configuration guide](/self-hosting/configuration) to fill in the missing values.
```sh theme={null}
cp .env.example .env
```
The database user should have the `SUPERUSER` role. You can setup and migrate
the database with the `bunx nx db:migrate prisma` command.
3. Install dependencies
```sh theme={null}
bun install
```
4. Run the database migrations
```sh theme={null}
bunx nx db:migrate prisma
```
5. Build the builder and viewer
```sh theme={null}
bunx nx run-many -t build -p builder,viewer
```
If you face the issue `Node ran out of memory`, then you should increase the
memory limit for Node.js. For example,`NODE_OPTIONS=--max-old-space-size=4096`
will increase the memory limit to 4GB. Check [this stackoverflow
answer](https://stackoverflow.com/questions/53230823/fatal-error-ineffective-mark-compacts-near-heap-limit-allocation-failed-javas)
for more information.
## Deployments
### Deploy the builder
From the repository root, start the builder with PM2:
```sh theme={null}
pm2 start bunx --name=typebot-builder -- nx start builder -- -p 3000
```
### Deploy the viewer
From the repository root, start the viewer with PM2:
```sh theme={null}
pm2 start bunx --name=typebot-viewer -- nx start viewer -- -p 3001
```
You can change the ports passed after `-p`. The PM2 commands must be run from
the repository root so Nx can resolve the workspace.
## Nginx configuration
You can use the following configuration to serve the builder and viewer with Nginx. Make sure to replace the `server_name` values with the respective domain names for your Typebot instance. They should match `NEXTAUTH_URL` and `NEXT_PUBLIC_VIEWER_URL`. Check out [this guide](https://www.coderrocketfuel.com/article/how-to-deploy-a-next-js-website-to-a-digital-ocean-server/) for a step-by-step guide on how to setup Nginx and PM2.
```nginx theme={null}
server {
listen 80;
server_name typebot.example.com;
return 301 https://typebot.example.com$request_uri;
}
server {
listen 443 ssl;
server_name typebot.example.com;
# managed by Certbot
ssl_certificate /etc/letsencrypt/live/typebot.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/typebot.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location ^~ / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name bot.example.com;
return 301 https://bot.example.com$request_uri;
}
server {
listen 443 ssl;
server_name bot.example.com;
# managed by Certbot
ssl_certificate /etc/letsencrypt/live/bot.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bot.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location ^~ / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# Necessary to enable message streaming
proxy_buffering off;
}
}
```
# Vercel
Source: https://docs.typebot.com/self-hosting/deploy/vercel
The easiest way to get started with Typebot is with [the official managed
service in the Cloud](https://app.typebot.io). You'll have high availability,
backups, security, and maintenance all managed for you by me, Baptiste,
Typebot's founder. The cloud version can save a substantial amount of
developer time and resources. For most sites this ends up being the best value
option and the revenue goes to funding the maintenance and further development
of Typebot. So you'll be supporting fair source software and getting a great
service!
## Requirements
You need a Postgres database hosted somewhere. For production, [Neon](https://typebot.com/neon) is my provider of choice. This is not an affiliate link; it is simply the provider I use and recommend for a production database. You can also use any compatible Postgres provider.
## Getting Started
Fork the repository
## Disable Github workflows
You may want to [disable the Github actions](https://docs.github.com/en/actions/using-workflows/disabling-and-enabling-a-workflow) as they are most likely not relevant to your use of Typebot. This can be done.
## Reduce function maxDuration (Hobby plan only)
If you deploy on a Vercel Hobby plan, you will need to reduce the `maxDuration` timeout options in `apps/viewer/vercel.json` and set it to `10`
* Builder is the application where you'll create your flows.
* Viewer is the bot interface your users will interact with.
### Deploy the builder
1. Create a new Vercel project and import the forked repo
2. Change the project name to: `typebot-builder` (or anything else)
3. Choose Next.js framework
4. Change the output directory to: `apps/builder/.next`
5. Change the build command to:
```sh theme={null}
bunx nx build builder && bunx nx db:migrate prisma
```
6. Add the required environment variables ([Check out the configuration guide](/self-hosting/configuration))
7. Hit "Deploy"
### Deploy the viewer
1. Create a new Vercel project and import the forked repo
2. Change the project name to: `typebot-viewer` (or anything else)
3. Choose Next.js framework
4. Change the output directory to: `apps/viewer/.next`
5. Change the build command to:
```sh theme={null}
bunx nx build viewer && bunx nx db:migrate prisma
```
6. Add the required environment variables ([Check out the configuration guide](/self-hosting/configuration))
7. Hit "Deploy"
# Overview
Source: https://docs.typebot.com/self-hosting/get-started
Typebot is fair source and can be self-hosted on your own server. This guide will walk you through the process of setting up your own instance of Typebot.
The easiest way to get started with Typebot is with [the official managed
service in the Cloud](https://app.typebot.io). You'll have high availability,
backups, security, and maintenance all managed for you by me, Baptiste,
Typebot's founder.
The cloud version can save a substantial amount of developer time and
resources. For most sites this ends up being the best value option and the
revenue goes to funding the maintenance and further development of Typebot. So
you'll be supporting fair source software and getting a great service!
| | [Typebot Cloud](https://app.typebot.io) | Self-Hosting |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Hosting | Easy and convenient. It takes 1 minute to start building your bots and share them with a worldwide high availability, backups, security and maintenance all done for you by me, [Baptiste, Typebot's founder](https://twitter.com/baptisteArno). I manage everything so you don’t have to worry about anything and can focus on creating great bot experiences. | You do it all yourself. You need to get a server and you need to manage your infrastructure. You are responsible for installation, maintenance, upgrades, server capacity, uptime, backup, security, stability, consistency, loading time and so on. |
| Storage | All visitor data is exclusively processed on EU-owned cloud infrastructure. This ensures that your bots data processing complies with GDPR. | You have full control and can host your instance on any server in any country that you wish. Host it on a server in your basement or host it with any cloud provider wherever you want. |
| Costs | I charge a subscription fee. Whether you're a solo business owner, a growing startup or a large company, Typebot is here to help you build high-performing chat forms for the right price. Pay for as little or as much usage as you need. | You need to pay for your server, your database, your S3 storage, backups and whatever other cost there is associated with running the infrastructure. You never have to pay any fees to us. |
| Features | Almost all features are available in the Free plan so that you can easily try it all out. More info available [here](https://typebot.io/pricing). | You have access to all the features. See how to configure default attributed workspace plan and admin user [here](./configuration). |
| Releases | Instant access to new features | New releases are published each beginning of the month. |
| Support | Premium direct support available on STARTER and PRO plans | We don't offer support for your self-hosting issues that are not related to Typebot. You may reach out to the [Discord community](https://typebot.io/discord) for support. |
## License requirements
Typebot is available under the Functional Source License (FSL).
You can find the full license [here](https://raw.githubusercontent.com/baptisteArno/typebot.io/main/LICENSE).
This license allows you to do anything with Typebot except undermine its producer. You can run it for almost all purposes, study it, modify it, and distribute your changes, including proposing improvements back to the producer. After two years it becomes permissive Open Source software under Apache 2.0.
[Sponsoring the
project](https://github.com/sponsors/baptisteArno) is a great way to give back
to the community and to contribute to the long-term sustainability of the
project. It also comes with some perks like priority support and private
workshops. ❤️
## FAQ
You can do anything with Typebot except undermine its producer. Here is a non-exhaustive list of things you can do with a self-hosted instance:
✅ As a company, create and publish your bot into your client-facing products
✅ As a freelancer, create bots for your clients
✅ Create (commercial) education / content about Typebot
✅ Do (commercial) research
Here is a non-exhaustive list of things you cannot do:
❌ Commercialize the access to your instance
❌ Offer services for hosting Typebot instances
❌ **You legally cannot do this**. If you are selling your software, integrating the Typebot editor would mean competing against Typebot Cloud, which violates the project's license. However, you can use the code from two years ago, which is available under the Apache 2.0 license.
❌ **You legally cannot do this**. This would mean you are competing against Typebot Cloud, which violates the project's license. However, you can use the code from two years ago, which is available under the Apache 2.0 license.
Typebot is fair source not because it is good business even though I think it creates instant trusts with prospects since the code is 100% public, it can be audited.
I personnally love when a software is open source. I get the chance to contribute to the code if I ever find a bug or need a new feature. When I benchmark 2 similar softwares, I almost always choose the one that is open source for that reason.
Everything I do with Typebot is to make it like a software I would personally love using.
Since I run Typebot as a solo entrepreneur, I also feel like making Typebot fair source is more sustainable as I can get the help from the community.
## Releases
The self-hosted version is somewhat of a LTS, you only get new release once a month. If you want features as soon as they are available, consider becoming a [cloud user](https://app.typebot.io). New versions are published on the [releases page](https://github.com/baptisteArno/typebot.io/releases).
## Ready to self-host?
Typebot is composed of 2 Next.js applications you need to deploy:
* the builder, where you build your typebots
* the viewer, where your user answer the typebot
### Database recommendation
Typebot needs a Postgres database. For production, [Neon](https://typebot.com/neon) is my database provider of choice. This is not an affiliate link; it is simply the provider I use and recommend for a production database. You can still use any compatible Postgres provider or host Postgres yourself.
I've written guides on how to deploy Typebot using:
* [Docker](./deploy/docker)
* [Vercel](./deploy/vercel)
* [Manual](./deploy/manual)
* [ALibaba Cloud](./deploy/alibaba-cloud)
If you have any questions, feel free to reach out on the [Discord server](https://typebot.io/discord) 🔥
# Using a PlanetScale database
Source: https://docs.typebot.com/self-hosting/guides/planetscale
Typebot is also pluggable to a PlanetScale database. But it means, you'll need to push schema changes manually.
To do so, follow these instructions:
1. Replace `DATABASE_URL` with a PlanetScale development branch URL.
2. From the `packages/prisma` directory, run a the db push command: `bun db:push`
3. Then, in PlanetScale dashboard, or using their CLI, you can create a new deploy request from this development branch to your production branch.
You can't connect to PlanetScale database if you are deploying with Docker as
docker images are currently built only with postgresql support.
# S3 Configuration
Source: https://docs.typebot.com/self-hosting/guides/s3
In order for Typebot to store your uploaded files, you need to configure an S3 bucket.
You can use any S3-compatible storage provider. Here are some examples:
* [AWS S3](https://aws.amazon.com/s3/)
* [Cloudflare R2](https://developers.cloudflare.com/r2/)
* [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/)
* [Wasabi](https://wasabi.com/)
* [MinIO](https://min.io/)
If you are self-hosting using Docker, you can follow the [docker-specific
instructions](../deploy/docker#s3-storage) to run a local S3-compatible
storage server.
To function properly, your S3 bucket must have the following configuration:
* CORS policy:
```json theme={null}
{
"CORSRules": [
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
}
```
If you are using the amazon console online you should paste it like this :
```json theme={null}
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
```
* Access policy (replace `` with the name of your S3 bucket):
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::/public/*"
}
]
}
```
## How to set up CORS policy?
Some S3 providers like AWS provide a user interface that allows you to directly enter a bucket policy. However, other providers might not provide such an interface. In this case, you can set up the CORS policy from the command line.
1. Make sure you have the AWS CLI (Command Line Interface) installed and configured on your machine. If you haven't done so already, refer to the official AWS CLI documentation for installation and configuration instructions.
2. Open your command-line interface (CLI), such as Terminal on macOS or Command Prompt on Windows.
3. Create a JSON file (e.g., cors-policy.json) that contains the desired CORS policy. Here's an example CORS policy that allows GET requests from all origins (\*):
```json theme={null}
{
"CORSRules": [
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
}
```
4. Run the following command, replacing `` with the name of your S3 bucket and `` with the file path to your JSON CORS policy file:
```bash theme={null}
aws s3api put-bucket-cors --bucket --cors-configuration file://
```
When the command is executed successfully, AWS will respond with the JSON representation of the CORS configuration. This indicates that the CORS policy has been applied to your S3 bucket.
Note: Ensure that you have the appropriate AWS credentials and permissions to perform this action.
## How to set up Access policy?
Some S3 providers like AWS provide a user interface that allows you to directly enter a bucket policy. However, other providers like DigitalOcean do not provide such a user interface. In this case, you can set up a bucket policy from the command line.
To set up an S3 bucket policy from the command line, you can use the AWS Command Line Interface (CLI). Here's a step-by-step guide:
1. Install and configure the AWS CLI on your machine if you haven't done so already. You can refer to the official AWS CLI documentation for instructions on installation and configuration.
2. Open your command-line interface (e.g., Terminal on macOS or Command Prompt on Windows).
3. To set up a bucket policy, you need the policy document in JSON format. Create a JSON file (e.g., bucket-policy.json) containing the desired policy. Here's an example policy that allows Public read access for all objects within the bucket:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::/public/*"
}
]
}
```
4. Replace `` with the name of your S3 bucket.
5. Run the following command, replacing `` with the name of your S3 bucket and `` with the file path to your JSON policy document:
```bash theme={null}
aws s3api put-bucket-policy --bucket --policy file://
```
After running the command, AWS will respond with the policy's JSON representation if the operation is successful. You should see the response output confirming the policy has been added to the bucket.
# Troubleshoot
Source: https://docs.typebot.com/self-hosting/troubleshoot
## My workspace is showing Free plan and 200 chats limit
You most likely forgot to set up an `ADMIN_EMAIL` variable or did not sign up using the specified email. You can also set the `DEFAULT_WORKSPACE_PLAN` variable to the value of your choice (`FREE`, `STARTER`, `PRO`, `LIFETIME`, `UNLIMITED`) to attribute the specified plan to all newly created workspaces. Otherwise, you can also directly connect to your database and update the `Workspace` table to change the plan of an existing workspace.
## I can't upload files
You need to add an [S3 configuration](./guides/s3#s3-storage-media-uploads) to your project. If you are self-hosting with Docker, you can [add a S3 service to your docker-compose file](./deploy/docker#s3-storage).
## Authentication fails or users are randomly logged out
When the login page only shows "Check server logs to see relevant error message", the cause is usually one of:
* **`ENCRYPTION_SECRET` was rotated.** Existing sessions and encrypted credentials become unreadable. Restore the previous value, or accept that users will need to sign in again and credentials (Google Sheets, OpenAI, SMTP…) re-created.
* **Builder and viewer have different secrets.** `ENCRYPTION_SECRET` must be identical on both services.
* **`NEXTAUTH_URL` doesn't match the URL users hit.** It must be the public builder URL with the correct scheme. Behind a reverse proxy, forward `Host` and `X-Forwarded-Proto`.
* **Database unreachable or reset.** Check `DATABASE_URL` and that the `User`, `Account` and `Session` tables are populated.
Tail the builder logs while reproducing the sign-in to surface the actual NextAuth / Prisma error.
# Settings
Source: https://docs.typebot.com/settings/overview
## General
The general settings represent the general behaviors of your typebot.
* **Prefill input**: If enabled, the inputs will be automatically pre-filled whenever their associated variable has a value.
* **Hide query params on bot start**: If enabled, the query params will be hidden when the bot starts.
* [**Remember user**](./remember-user)
* **System messages**: You can overwrite any system message of your bot, it includes the default invalid message bot response, the network error message, the bot is closed, etc.
## Typing emulation
By default, your typebot will emulate a certain typing speed. It is considered a good default as slow as a human typing speed and it's not too fast so that multiple bubbles can be read sequentially.
You can customize this typing speed in the settings:
The goal of a typebot is not to pretend that the bot is a real human. So we suggest not setting the typing speed too low.
The `Disable on first message` allows you to disable the typing emulation on the first message. This is useful if you want to lower the first message display time since the site can take some time to load first.
The `Delay between messages` by default is 0 and you can increase it up to 5 seconds if you want to add a delay between **every** messages sent by the typebot. If you ever want to pause the bot just once. You can insert a [Wait block](../editor/blocks/logic/wait) between both messages.
## Security
By default, your typebot can be executed from any origin but you can restrict the execution of your typebot to specific origins. This is useful if you want to embed your typebot in your website and prevent it from being executed on other websites by malicious actors.
For example, if you want to allow your typebot to be executed only on `https://my-company.com`, you can add `https://my-company.com` to the list of allowed origins.
If you add a URL to the list but omit [https://typebot.co](https://typebot.co), then your typebot
shareable URL will not work anymore.
## Metadata
In the Metadata section, you can customize how the preview card will look if you share your bot URL on social media for example.
You can also add some custom head code to add third-party scripts.
### Icon, image, title and description
* **Icon**: The small icon shown in the browser tab of your bot’s standalone page. Click the icon preview in Metadata to upload a new one. Recommended format: PNG or SVG, 32×32 or 48×48. If you embed your Typebot inside an existing website, the website’s favicon is used instead.
* **Image (social share image)**: Displayed when your bot link is shared on social networks and messaging apps. Recommended size: 1200×630 px (1.91:1 ratio), JPG or PNG. Keep the file reasonably small for faster loading.
* **Title**: Used for the page `` and Open Graph `og:title`. If left empty, your bot name is used.
* **Description**: Used for the meta description and Open Graph `og:description`. If left empty, a sensible default description is used.
* **Allow indexing**: Toggle to allow search engines to index your bot’s standalone page. Disable it if you want to keep it out of search results.
### Troubleshooting: I don’t see my new metadata
* **Hard refresh your browser**: Clear cache or perform a hard reload to fetch the latest favicon and meta tags.
* **Force social platforms to re-scrape**: Social networks cache previews aggressively. Use their tools to refresh:
* [Facebook Sharing Debugger](https://developers.facebook.com/tools/debug/)
* [X Card Validator](https://cards-dev.x.com/validator)
* [LinkedIn Post Inspector](https://www.linkedin.com/post-inspector/)
* **If you embed the bot**: The parent page controls favicon and Open Graph tags. Update the metadata in your website rather than in the bot settings.
* **Give it a few minutes**: Caches can take a short time to expire. Search engines may also reflect changes after their next crawl, especially if indexing is enabled.
### Google Tag Manager
Allows you to easily add a GTM container to your bot. To find your GTM container ID, go to your GTM dashboard and click on the container you want to use. The ID is displayed in the top right corner.
Note that you should not include it if you are embedding your typebot in an existing website. GTM should be installed in the parent website instead.
# Remember user
Source: https://docs.typebot.com/settings/remember-user
Head over to the `Settings` tab of your typebot, under the `General` section you can find the `Remember user` setting.
This setting allows you to save the chat session state into the user's web browser storage. It means that if he answers a question and then closes the chat, the next time he opens it, the chat will be in the same state as it was before.
There are 2 storage options:
* **Local storage**: The chat state will be saved in the user's web browser. It will be available only on the same device and web browser.
* **Session storage**: The chat state will be saved in the user's web browser. It will be available only on the same device and web browser, but it will be deleted when the user closes the current tab or the web browser.
Note that if you publish a new version of your typebot, saved sessions will be automatically resetted. It means that if the user has a saved session, if he refreshes the bot and that a new version is published, the bot will restart from the beginning.
# Font
Source: https://docs.typebot.com/theme/font
You can change the font of your typebot in the Theme tab under the Global section.
There, you can choose between choosing a font from Google Fonts or defining your own custom font.
## How to import my own font?
You can import your own font by clicking on the "Custom" option. There you need to define the font family and the CSS that defines all the `@font-face` properties.
For example, if I want to import my font called "Awesome Font", I would define the following family value: `"Awesome Font", "Helvetica Neue", sans-serif`. This should be a list of font names separated by commas. The first font name in the list is the font that will be used if it is available. If the name is not available, the browser will try to use the next font in the list. A font name that contains white-space should be quoted.
Then I would define the content like so:
```css theme={null}
@font-face {
font-family: 'Awesome Font';
src: url('https://example.com/awesome.woff') format('woff'), url('https://example.com/awesome.ttf') format('truetype');
}
```
The server providing the fonts (`https://example.com/awesome.woff`) needs to support HTTPS and Cross-Origin Resource Sharing (CORS).
# Theme
Source: https://docs.typebot.com/theme/overview
The theme tab allows you to customize the look of your typebot.
## Global
This section allows you to enable or disable the typebot branding, change the font and the background of your bot.
Toggling the **Typebot branding** option (or any other theme change) only
affects the live bot once you [republish](./../editor/publish) it. If you have
just disabled the branding but still see it on your published bot, hit the
**Publish** button to propagate the change.
### Progress Bar
The Progress Bar allows you to visually indicate a user’s progress through the bot. This helps improve user experience by providing a sense of advancement and completion.
To enable the progress bar in your chatbot:
1. Navigate to the Theme tab of your typebot.
2. Locate the Progress Bar option in the Global section.
3. Toggle the `Enable progress bar` switch to activate it.
| Option | Description |
| -------------------------- | ------------------------------------------------------------------------------------------ |
| **Placement** | Determines where the bar appears. Options: `Top` or `Bottom`. |
| **Background color** | Sets the color of the bar’s background. |
| **Color** | Sets the color of the progress indicator. |
| **Thickness** | Controls the height of the bar in pixels. Default: `4`. |
| **Position when embedded** | Controls how the bar is positioned when the bot is embedded on another website. See below. |
#### Position When Embedded
Use this option to adjust how the progress bar behaves when Typebot is embedded in a webpage:
* `fixed`: Pins the progress bar to the top of the window. It stays visible even if the chat container scrolls.
* `absolute`: Positions the progress bar at the top of the embedded chat container. It scrolls with the chat.
## Chat
This section allows you to customize all the chats components (avatars, bubbles, inputs etc...).
Click on the bot avatar to change the image:
## Custom CSS
You can also decide to customize even further by adding any custom CSS you want. For this you right-click on the bot in the Theme page and inspect the element you want to customize:
For example, if I want my buttons to be more rounded, and have a fancy gradient color, I can add this to the custom CSS:
```css theme={null}
.typebot-button {
border-radius: 40px;
background-image: linear-gradient(to right, #e052a0, #f15c41);
border: none;
}
```
### Customize a single button color
Thanks to custom CSS, you can customize the color of a single button for example by using the `data-itemid` attribute:
```css theme={null}
[data-itemid="cl3iunm4p000f2e6gfr8cznnn"] {
background-color: gray;
border-color: gray;
}
```
To find the item ID of a button, right-click on the button and inspect the element:
# Credentials
Source: https://docs.typebot.com/user/credentials
Credentials are used to connect Typebot to other services securely. These credentials can have 2 different scopes: **User** or **Workspace**.
User credentials are credentials that are associated with a user. Only you, as the user, can use them. It's useful when a user preference setting is required to use a service.
Workspace credentials are credentials that are associated with a workspace. They can be used by all members of the workspace. When you create a new credential in your bot, it will be created as a workspace credential by default.
You can view and manage your credentials by going to the `Credentials` tab in the `Settings & Members` menu.
# Delete account
Source: https://docs.typebot.com/user/delete-account
You can ask to delete your account and all its associated data by sending an email to [support@typebot.io](mailto:support@typebot.io). We will send a confirmation email within 72h.
# User preferences
Source: https://docs.typebot.com/user/preferences
## Change language
You can change the language of the application by going to your `Settings & Members` menu under the `Preferences` tab.
The application is still being translated, so some parts may not be translated
yet. This is tracked in [this
issue](https://github.com/baptisteArno/typebot.io/issues/955).
## Generate groups title with AI
You can automatically have your group titles generated with AI by going to your `Settings & Members` menu under the `Preferences` tab.
Here you'll have to configure your AI provider.
If you don't see your provider credentials listed that's because you don't have it in your personal user credentials. [See distinction between worksapce and user credentials.](./credentials)
Once enabled and properly configured, you'll see default group titles (starting with "Group #") changing whenever you connect a new group/block from this group.
# Overview
Source: https://docs.typebot.com/workspace
Everything you do in Typebot takes place in a workspace it's like a home. A workspace has members. It can be only you, your team, or the entire company.
Your plan is tied to your workspace. It means that if you have a Personal Pro workspace and you create a new workspace it will be by default a Free workspace.
You can create as many workspaces as you want.
## Switch workspace
When you belong to several workspaces (for example, a personal workspace and a team workspace you were invited to), you can switch between them at any time from the workspace dropdown at the top-left of the dashboard:
If you log in and can't find your bots, you are most likely viewing a different workspace than the one that owns them. Open the dropdown and pick the right workspace. If the expected workspace is missing, make sure you are logged in with the email address that was invited to it.
## Members
Someone is a member of a workspace when he has access to the whole workspace. Once someone is a member of a workspace, he will be will have this workspace visible in his workspaces dropdown:
## Admins
Administrators are the people who can manage the workspace. Invite new members, check the workspace settings, billing, and more.
## Delete a workspace
You can delete a workspace by navigating to the workspace settings:
# Add members and guests
Source: https://docs.typebot.com/workspace/add-members-and-guests
There are several ways users can interact with a Typebot workspace:
* Admins: admins who can manage workspace settings, delete a workspace, and manage other admins, members, and guests.
* Members: People on your team who can create and edit typebots, but not edit settings or add members.
* Guests: People external to your team who you want to work with on specific typebots. They can be invited to individual typebots, but not an entire workspace. They can't be given workspace-wide access. They must be invited to individual typebots to view them.
## How to invite admins and members
In your workspace, click on the **Settings & Members** button and then the **Members** tab.
You will see your Workspace members list:
There you can invite new admins or members and set existing members as admins.
## How to invite guests
In your typebot, click on the **Invite users to collaborate** icon button.
You will see the guests list and who has access to this particular typebot.
Guests can either:
* View the typebot: they will be able to view the flow and the results but they will not be able to modify the flow.
* Edit the typebot: they will be able to view **AND** edit the flow and the results
# Subscription
Source: https://docs.typebot.com/workspace/subscription
## Upgrade plan
In order to upgrade your workspace plan and increase your monthly limits, you need to open the `Settings & Members` modal in your homepage and navigate on the `Billing & Usage` tab.
This tab displays your bots total usage, your current plan and paid invoices.
You can choose to upgrade to your desired plan here.
## Cancel or downgrade plan
To cancel or downgrade your workspace plan:
From your homepage, open the `Settings & Members` modal.
Navigate to the `Billing & Usage` tab.
Click the `Billing portal` button. This redirects you to the Stripe-hosted billing portal.
From the billing portal you can cancel your subscription or switch to a different plan.
Once the current billing period ends, the workspace automatically reverts to the **Free** plan.
## Add a VAT ID for B2B reverse charge
If you are a VAT-registered business in the EU (outside of France), you can add your VAT ID to your billing details so that future invoices are issued under the reverse charge mechanism, without VAT.
From your homepage, open the `Settings & Members` modal, navigate to the `Billing & Usage` tab and click `Billing portal`.
In the billing portal, click `Update information` in the billing details section.
Click `Add tax ID`, pick your country prefix (for example `EU VAT`) and paste your VAT number, then save.
Adding a VAT ID only affects **future invoices**. Past invoices cannot be reissued without VAT, even after a valid VAT ID is added. Add your VAT ID before your next renewal to make sure the reverse charge is applied.
Without a valid VAT ID on file, your billing country's destination VAT is charged on every invoice as for a standard B2C customer.
## Free plan limits
When your workspace is on the Free plan, the following limits apply:
* **200 chats per month.** A chat is counted once a user starts a conversation with your bot. Additional messages from the same user within the same session do not count.
* **1 seat.** You cannot invite members to a Free workspace. To collaborate with others, upgrade to Starter or above.
Higher limits are available on Starter, Pro, and Enterprise plans. See the [pricing page](https://typebot.com/pricing) for an up-to-date comparison.