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

# Edit bot

> Partially updates an existing Typebot bot on the instance

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

## Description

Updates an existing Typebot bot on the instance. This is a **partial** update: only the fields you send are changed, every other field keeps its current value. After saving, RyzeAPI activates the instance's integration.

<Info>
  The bot to edit is identified by `botId` in the body (required).
</Info>

<Note>
  **Partial semantics**, omit a field to leave it untouched. To *clear* a text field, send it explicitly as an empty string (`""`). To create a new bot instead, use [`POST /api/typebot/set/:instance`](/en/api/typebot/set).
</Note>

<Warning>
  Changing `enabled`, `triggerType`, `triggerOperator` or `triggerValue` is still subject to the uniqueness rules: each instance can have only **one** enabled `all` bot, and `keyword` bots are unique per `(triggerOperator, triggerValue)`. A conflicting change returns `400`.
</Warning>

## Example

Editing only a couple of fields (enable the bot and change the expiration):

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH "https://ryzeapi.cloud/api/typebot/update/suporte" \
    -H "token: $Token_Account" \
    -H "Content-Type: application/json" \
    -d '{
      "botId":         "8f3a1c2e-...-b7d9",
      "enabled":       true,
      "expireMinutes": 45
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch("https://ryzeapi.cloud/api/typebot/update/suporte", {
    method: "PATCH",
    headers: {
      "token":        process.env.Token_Account,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      botId:         "8f3a1c2e-...-b7d9",
      enabled:       true,
      expireMinutes: 45
    })
  });
  ```

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

  requests.patch(
      "https://ryzeapi.cloud/api/typebot/update/suporte",
      headers={
          "token":        os.environ["Token_Account"],
          "Content-Type": "application/json"
      },
      json={
          "botId":         "8f3a1c2e-...-b7d9",
          "enabled":       True,
          "expireMinutes": 45
      }
  )
  ```

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

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

  func main() {
      body := strings.NewReader(`{
          "botId":         "8f3a1c2e-...-b7d9",
          "enabled":       true,
          "expireMinutes": 45
      }`)
      req, _ := http.NewRequest("PATCH", "https://ryzeapi.cloud/api/typebot/update/suporte", body)
      req.Header.Set("token", os.Getenv("Token_Account"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

<Tip>
  You only need to send `botId` plus the fields you want to change. In the example above `typebotUrl`, `triggerType`, `description` and every other field keep their current values.
</Tip>

## Success response

```json 200 OK theme={null}
{
  "success": true,
  "message": "typebot bot updated",
  "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": 45,
    "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": 2,
    "last_activity_at": "2026-07-27T13:58:40Z",
    "created_at": "2026-07-20T09:12:00Z",
    "updated_at": "2026-07-27T14:05:22Z"
  }
}
```

| Field     | Description                                                                                                                                         |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `success` | Always `true` on success.                                                                                                                           |
| `message` | Fixed confirmation message (`typebot bot updated`).                                                                                                 |
| `bot`     | The full bot after the update, with all fields (including the ones you did not change). See the fields in the [list of bots](/en/api/typebot/list). |

## 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="botId" type="string" required>
  UUID of the bot to edit, obtained from [`GET /api/typebot/list/:instance`](/en/api/typebot/list).
</ParamField>

<ParamField body="typebotUrl" type="string">
  New URL of the **published** Typebot (viewer). Must be a valid URL. The trailing `/` is removed.
</ParamField>

<ParamField body="triggerType" type="string">
  How the bot is triggered: `all` or `keyword`.
</ParamField>

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

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

<ParamField body="enabled" type="boolean">
  Whether the bot is active in routing.
</ParamField>

<ParamField body="description" type="string">
  Bot label in the panel.
</ParamField>

<ParamField body="expireMinutes" type="integer">
  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.
</ParamField>

<ParamField body="keywordFinish" type="string">
  Word that, when sent by the user, ends the bot immediately.
</ParamField>

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

<ParamField body="typingDelayMs" type="integer">
  Delay of the "typing..." indicator before each reply, in milliseconds.
</ParamField>

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

<ParamField body="debounceSeconds" type="integer">
  Groups fragments sent by the customer for N seconds before processing.
</ParamField>

<ParamField body="ignoreGroups" type="boolean">
  If `true`, group messages do not trigger the bot.
</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, missing `botId`, invalid `typebotUrl`, or `triggerType` outside `all`/`keyword`. |
|  400 | `triggerOperator and triggerValue are required when triggerType is 'keyword'` | Set `triggerType: "keyword"` without operator/value.                                             |
|  400 | `this instance already has an enabled 'all' trigger bot`                      | The change would create a second enabled `all` bot (uniqueness).                                 |
|  400 | `another enabled bot already uses this trigger operator+value`                | The change collides with an existing enabled `keyword` bot.                                      |
|  404 | `instance not found`                                                          | Instance does not exist in RyzeAPI.                                                              |
|  404 | `bot not found for this instance`                                             | The `botId` provided does not exist in this instance.                                            |
|  500 | `update 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

`botId` that does not belong to the instance:

```json theme={null}
{
  "success": false,
  "error": {
    "message": "bot not found for this instance"
  }
}
```

## Next

<CardGroup cols={2}>
  <Card title="List bots" icon="list" href="/en/api/typebot/list">
    Confirm the new values with `GET /api/typebot/list/:instance`.
  </Card>

  <Card title="Create bot" icon="robot" href="/en/api/typebot/set">
    Add another bot with `POST /api/typebot/set/:instance`.
  </Card>
</CardGroup>
