> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ryzeapi.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Create bot

> Creates a new Typebot bot on the instance (create only)

**Auth:** `TokenAccount` or `TokenInstance` • **Rate limit:** `Global` (100/min) • **Idempotent:** no

## Description

Creates a **new** Typebot bot for the instance. RyzeAPI activates the instance's integration.

<Warning>
  This endpoint is **create-only**. Passing `botId` in the body returns **`400`** `botId is not allowed on create, use PATCH /api/typebot/update/:instance to edit`. To change an existing bot, use [`PATCH /api/typebot/update/:instance`](/en/api/typebot/update).
</Warning>

<Note>
  **Trigger priority**, when several rules can match the same message, the most specific wins:

  ```
  equals > startsWith / endsWith > contains > regex > all
  ```

  **Uniqueness**, each instance can have only **one** enabled `all` bot; `keyword` bots are unique per combination of `(triggerOperator, triggerValue)`. Trying to create a conflict returns `400`.
</Note>

<Warning>
  The `typebotUrl` must point to a **published** Typebot (viewer). The trailing `/` is removed. This operation has an internal timeout of **60s**.
</Warning>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/typebot/set/suporte" \
    -H "token: $Token_Account" \
    -H "Content-Type: application/json" \
    -d '{
      "typebotUrl":      "https://typebot.co/meu-bot-abc123",
      "triggerType":     "keyword",
      "triggerOperator": "contains",
      "triggerValue":    "orçamento",
      "enabled":         true,
      "description":     "Bot de orçamento",
      "expireMinutes":   30,
      "expireMessage":   "Sessão encerrada por inatividade.",
      "keywordFinish":   "sair",
      "finishMessage":   "Até logo! 👋",
      "typingDelayMs":   1500,
      "stopBotFromMe":   true,
      "debounceSeconds": 6,
      "ignoreGroups":    true
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch("https://ryzeapi.cloud/api/typebot/set/suporte", {
    method: "POST",
    headers: {
      "token":        process.env.Token_Account,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      typebotUrl:      "https://typebot.co/meu-bot-abc123",
      triggerType:     "keyword",
      triggerOperator: "contains",
      triggerValue:    "orçamento",
      enabled:         true,
      description:     "Bot de orçamento",
      expireMinutes:   30,
      expireMessage:   "Sessão encerrada por inatividade.",
      keywordFinish:   "sair",
      finishMessage:   "Até logo! 👋",
      typingDelayMs:   1500,
      stopBotFromMe:   true,
      debounceSeconds: 6,
      ignoreGroups:    true
    })
  });
  ```

  ```python Python theme={null}
  import os, requests

  requests.post(
      "https://ryzeapi.cloud/api/typebot/set/suporte",
      headers={
          "token":        os.environ["Token_Account"],
          "Content-Type": "application/json"
      },
      json={
          "typebotUrl":      "https://typebot.co/meu-bot-abc123",
          "triggerType":     "keyword",
          "triggerOperator": "contains",
          "triggerValue":    "orçamento",
          "enabled":         True,
          "description":     "Bot de orçamento",
          "expireMinutes":   30,
          "expireMessage":   "Sessão encerrada por inatividade.",
          "keywordFinish":   "sair",
          "finishMessage":   "Até logo! 👋",
          "typingDelayMs":   1500,
          "stopBotFromMe":   True,
          "debounceSeconds": 6,
          "ignoreGroups":    True
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "typebotUrl":      "https://typebot.co/meu-bot-abc123",
          "triggerType":     "keyword",
          "triggerOperator": "contains",
          "triggerValue":    "orçamento",
          "enabled":         true,
          "description":     "Bot de orçamento",
          "expireMinutes":   30,
          "expireMessage":   "Sessão encerrada por inatividade.",
          "keywordFinish":   "sair",
          "finishMessage":   "Até logo! 👋",
          "typingDelayMs":   1500,
          "stopBotFromMe":   true,
          "debounceSeconds": 6,
          "ignoreGroups":    true
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/typebot/set/suporte", body)
      req.Header.Set("token", os.Getenv("Token_Account"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

<Tip>
  For the simplest bot, send only `typebotUrl` + `triggerType: "all"`: it responds to any message. To **edit** an existing bot, use [`PATCH /api/typebot/update/:instance`](/en/api/typebot/update) with its `botId`, this endpoint only creates.
</Tip>

## Success response

```json 201 Created theme={null}
{
  "success": true,
  "message": "typebot bot created",
  "bot": {
    "id": "8f3a1c2e-...-b7d9",
    "instance_id": "...",
    "enabled": true,
    "description": "Bot de orçamento",
    "typebot_url": "https://typebot.co/meu-bot-abc123",
    "trigger_type": "keyword",
    "trigger_operator": "contains",
    "trigger_value": "orçamento",
    "expire_minutes": 30,
    "expire_message": "Sessão encerrada por inatividade.",
    "keyword_finish": "sair",
    "finish_message": "Até logo! 👋",
    "typing_delay_ms": 1500,
    "stop_bot_from_me": true,
    "debounce_seconds": 6,
    "ignore_groups": true,
    "no_start_from_me": false,
    "keep_open": false,
    "active_sessions": 0,
    "created_at": "2026-07-27T14:03:11Z",
    "updated_at": "2026-07-27T14:03:11Z"
  }
}
```

| Field     | Description                                                                                                   |
| --------- | ------------------------------------------------------------------------------------------------------------- |
| `success` | Always `true` on success.                                                                                     |
| `message` | Fixed confirmation message (`typebot bot created`).                                                           |
| `bot`     | The created bot, already with its generated `id`. See the fields in the [list of bots](/en/api/typebot/list). |
| `bot.id`  | Bot UUID, used in `update`, `list?botId=` and `delete?botId=`.                                                |

## Path parameters

<ParamField path="instance" type="string" required>
  Instance name (e.g., `suporte`).
</ParamField>

## Headers

<ParamField header="token" type="string" required>
  `TokenAccount` or `TokenInstance`.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Request body

<ParamField body="typebotUrl" type="string" required>
  URL of the **published** Typebot (viewer). Must be a valid URL. The trailing `/` is removed. Ex.: `https://typebot.co/meu-bot-abc123`.
</ParamField>

<ParamField body="triggerType" type="string" required>
  How the bot is triggered: `all` (any message starts the flow) or `keyword` (only when the message matches `triggerOperator` + `triggerValue`).
</ParamField>

<ParamField body="triggerOperator" type="string">
  Trigger operator, **required if** `triggerType` is `keyword`. One of: `contains`, `equals`, `startsWith`, `endsWith`, `regex`.
</ParamField>

<ParamField body="triggerValue" type="string">
  Trigger word or expression, **required if** `triggerType` is `keyword`.
</ParamField>

<ParamField body="enabled" type="boolean" default="true">
  Whether the bot is active in routing. Absent equals `true`.
</ParamField>

<ParamField body="description" type="string">
  Bot label in the panel (e.g., `"Bot de orçamento"`).
</ParamField>

<ParamField body="expireMinutes" type="integer" default="0">
  Expires the session by inactivity after N minutes. `0` = never expires.
</ParamField>

<ParamField body="expireMessage" type="string">
  Message sent to the user when the session expires (if defined).
</ParamField>

<ParamField body="keywordFinish" type="string">
  Word that, when sent by the user, ends the bot immediately (e.g., `"sair"`).
</ParamField>

<ParamField body="finishMessage" type="string">
  Farewell sent when the bot is ended by the `keywordFinish`.
</ParamField>

<ParamField body="typingDelayMs" type="integer" default="0">
  Delay of the "typing..." indicator before each reply, in milliseconds (converted to seconds on send).
</ParamField>

<ParamField body="stopBotFromMe" type="boolean" default="false">
  If `true`, the bot is paused in that conversation when you (the operator) reply manually.
</ParamField>

<ParamField body="debounceSeconds" type="integer" default="0">
  Groups fragments sent by the customer for N seconds before processing (avoids firing the flow on every line).
</ParamField>

<ParamField body="ignoreGroups" type="boolean" default="true">
  If `true`, group messages do not trigger the bot. Absent equals `true`.
</ParamField>

<ParamField body="noStartFromMe" type="boolean" default="false">
  If `true`, the bot does not auto-start when **you** started the conversation. When you send the first message and the contact replies, the bot does not trigger. The reactivation window reuses `expireMinutes` (counted from your first message; `0` = permanent).
</ParamField>

<ParamField body="keepOpen" type="boolean" default="false">
  If `true`, when the flow ends the conversation stays open instead of closing. The bot stays silent (it does not restart) and the session only ends via `keywordFinish` or manually, appearing with status `held`.
</ParamField>

## Errors

| HTTP | `error.message`                                                                   | Cause                                                                           |
| :--: | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|  400 | `invalid body: ...`                                                               | Malformed body, invalid `typebotUrl`, or `triggerType` outside `all`/`keyword`. |
|  400 | `botId is not allowed on create, use PATCH /api/typebot/update/:instance to edit` | `botId` was sent on create. Use `PATCH /update` to edit.                        |
|  400 | `triggerOperator and triggerValue are required when triggerType is 'keyword'`     | `triggerType: "keyword"` without operator/value.                                |
|  400 | `this instance already has an enabled 'all' trigger bot`                          | An enabled `all` bot already exists (uniqueness).                               |
|  400 | `another enabled bot already uses this trigger operator+value`                    | An enabled `keyword` bot with the same `(operator, value)` already exists.      |
|  404 | `instance not found`                                                              | Instance does not exist in RyzeAPI.                                             |
|  500 | `create bot: ...` / `activate typebot: ...`                                       | Local persistence failure, or failure activating the integration.               |
|  503 | `integration gateway not configured`                                              | Integration service unavailable on the server.                                  |

### Error payload example

`keyword` trigger without operator/value:

```json theme={null}
{
  "success": false,
  "error": {
    "message": "triggerOperator and triggerValue are required when triggerType is 'keyword'"
  }
}
```

## Next

<CardGroup cols={2}>
  <Card title="Edit bot" icon="pen" href="/en/api/typebot/update">
    Change fields of an existing bot with `PATCH /api/typebot/update/:instance`.
  </Card>

  <Card title="List bots" icon="list" href="/en/api/typebot/list">
    Check all the instance's bots and the integration status.
  </Card>
</CardGroup>
