Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,18 @@ description: Краткое описание для SEO

### Обновление API (changelog)

В `content/updates.mdx`:
Создайте файл `content/updates/<ГГГГ-ММ-ДД>.md` (один файл на дату) с frontmatter и markdown-телом:

```md
<!-- update:2025-12-01 -->
## Название обновления
---
date: "2025-12-01"
title: "Название обновления"
---

- [Новый метод](POST /messages)
```

Badge «Новое» показывается < 7 дней. Попадает в RSS feed.
Badge «Новое» показывается < 7 дней. Попадает в RSS feed. Полные правила — [docs/updates-format.md](docs/updates-format.md).

### Кастомная схема для гайда

Expand Down
4 changes: 3 additions & 1 deletion apps/docs/content/api/models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ hideTableOfContents: true
<Card title="Реакция на сообщение" href="#reaktsiya-na-soobschenie" methods="GET POST DELETE" />
<Card title="Напоминание" href="#napominanie" methods="GET POST PUT DELETE" />
<Card title="Представление" href="#predstavlenie" methods="POST" />
<Card title="Параметры бота" href="#parametry-bota" methods="PUT" />
<Card title="Параметры бота" href="#parametry-bota" methods="POST, GET, PUT" />
<Card title="Событие исходящего вебхука" href="#sobytie-ishodyaschego-vebhuka" methods="GET DELETE" />
<Card title="Событие аудита" href="#sobytie-audita" methods="GET" />
</CardGroup>
Expand Down Expand Up @@ -153,6 +153,8 @@ hideTableOfContents: true

## Параметры бота

- [Создание бота](POST /bots)
- [Получение бота](GET /bots/{id})
- [Редактирование бота](PUT /bots/{id})

<ModelSchema name="BotResponse" />
Expand Down
24 changes: 22 additions & 2 deletions apps/docs/content/guides/bots/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ related:

# Создание и настройка

## Создание бота
Бота можно создать двумя способами:

- **Через интерфейс** — больше настроек (тип бота, аватар, доступы, шаблоны входящего вебхука) и наглядная пошаговая форма. Подходит для разовой ручной настройки.
- **Через API** ([Создание бота](POST /bots)) — программно, без интерфейса. Подходит для автоматизации: завести бота из своего сервиса или скрипта и сразу получить `access_token`.

## Создание бота через интерфейс

<Warning>
Создание и настройка ботов доступны в веб-версии и десктопном приложении Пачки. В мобильных приложениях (iOS и Android) эта возможность недоступна.
Создание и настройка ботов через интерфейс доступны в веб-версии и десктопном приложении Пачки. В мобильных приложениях (iOS и Android) эта возможность недоступна.
</Warning>

Для создания бота перейдите в **Автоматизации** > **Интеграции** > **Чат-боты и Вебхуки** и нажмите кнопку **«+»**.
Expand Down Expand Up @@ -43,6 +48,21 @@ related:
</Step>
</Steps>

## Создание бота через API

Бота можно создать программно методом [Создание бота](POST /bots) — без интерфейса. Это удобно, когда нужно завести бота из своего сервиса или скрипта.

<Steps>
<Step title="Отправьте запрос на создание">
Передайте параметры бота в объекте `bot.webhook`: имя, никнейм, Webhook URL, список событий и команды. Никнейм должен заканчиваться на `_bot`.
</Step>
<Step title="Сохраните access_token">
В ответе вы получите `access_token` бота — сразу сохраните его. Повторно получить токен вы сможете только через интерфейс (вкладка **API** настроек бота), там же его можно перевыпустить. Вместе с токеном придёт `id` бота (его `user_id`).
</Step>
</Steps>

Получить параметры существующего бота можно методом [Получение бота](GET /bots/{id}), а изменить — методом [Редактирование бота](PUT /bots/{id}).

## Профиль бота

Бот, как и любой участник пространства, имеет свой профиль. В нём отображаются имя, аватар, никнейм, статус и список общих чатов с ботом. Профиль бота можно редактировать — изменить имя, никнейм и другие поля.
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/guides/cli/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pachca doctor
# ✔ Конфиг ~/.config/pachca/config.toml (права: 600)
# ✔ Профиль personal (user: Иван Иванов)
# ✔ Токен действителен (11 скоупов)
# ✔ CLI v2026.5.2 (актуальная версия)
# ✔ CLI v2026.6.0 (актуальная версия)
```

## Обновление
Expand Down
19 changes: 19 additions & 0 deletions apps/docs/content/updates/2026-06-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
date: "2026-06-15"
title: "Создание ботов через API, голосовые сообщения"
---

Теперь бота можно создать и получить через API, а не только в интерфейсе. При создании вы получите `access_token` бота — сразу сохраните его, повторно получить токен можно только через интерфейс.

Новые и обновлённые методы для ботов:

- [Создание бота](POST /bots)
- [Получение бота](GET /bots/{id})
- [Редактирование бота](PUT /bots/{id})

Появилась поддержка голосовых сообщений. В сообщении возвращается объект `voice_content` с длительностью, формой волны и расшифровкой, а при отправке файла с `file_type` = `voice` принимаются параметры `duration_ms` и `waveform`.

- [Отправка нового сообщения](POST /messages)
- [Редактирование сообщения](PUT /messages/{id})

В payload вебхука реакции поле `created_at` теперь приходит и при удалении реакции. Также в деталях события аудита DLP поле `action_message` может быть `null`, если у действия правила не задан текст.
56 changes: 56 additions & 0 deletions apps/docs/data/releases.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,60 @@
[
{
"product": "cli",
"version": "2026.6.0",
"date": "2026-06-15",
"changes": [
{
"type": "+",
"command": "bots create",
"description": "Новая команда — создание бота и получение его access_token"
},
{
"type": "+",
"command": "bots get",
"description": "Новая команда — получение параметров бота"
},
{
"type": "~",
"command": "bots update",
"description": "Расширены поля редактирования бота: name, nickname, events, trigger_on, commands"
},
{
"type": "+",
"description": "В сообщениях появилось поле voice_content и параметры файлов duration_ms / waveform для голосовых сообщений"
}
]
},
{
"product": "n8n",
"version": "2.0.10",
"date": "2026-06-15",
"changes": [
{
"type": "+",
"description": "Создание и получение ботов через API (POST /bots, GET /bots/{id})"
},
{
"type": "+",
"description": "Поддержка голосовых сообщений: поле voice_content и параметры duration_ms / waveform"
}
]
},
{
"product": "sdk",
"version": "1.0.22",
"date": "2026-06-15",
"changes": [
{
"type": "+",
"description": "Методы создания и получения ботов: POST /bots, GET /bots/{id}"
},
{
"type": "+",
"description": "Поле voice_content в сообщении и параметры файлов duration_ms / waveform для голосовых сообщений"
}
]
},
{
"product": "sdk",
"version": "1.0.21",
Expand Down
31 changes: 21 additions & 10 deletions apps/docs/lib/code-generators/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,15 @@ function valueToFlag(
}
} else if (typeof value === 'object') {
parts.push(`--${flag}='${JSON.stringify(value)}'`);
} else if (typeof value === 'number' || typeof value === 'bigint') {
parts.push(`--${flag}=${value}`);
} else {
const strValue = String(value);
if (strValue.includes(' ')) {
// Квотируем только если в значении есть пробел или shell-метасимвол.
// Простые URL, идентификаторы, enum-значения и slug-и остаются без кавычек
// (по соглашению gh / Vercel / Heroku / AWS). Реальные URL с `?...&...`
// пользователь сам должен взять в кавычки при копировании.
if (/[\s&|;()<>*?$`\\'"#]/.test(strValue)) {
parts.push(`--${flag}="${strValue}"`);
} else {
parts.push(`--${flag}=${strValue}`);
Expand Down Expand Up @@ -190,9 +196,9 @@ function extractUnwrappedBodyFields(
if (s.readOnly) continue;
if (options?.requiredOnly && !innerRequired.includes(name)) continue;
const example = generateExample(s, 0, options);
if (example !== undefined) {
fields.push({ name, example, schemaType: s.type, format: s.format });
}
if (example === undefined) continue;
if (isRedundantDefault(s, innerRequired.includes(name), example)) continue;
fields.push({ name, example, schemaType: s.type, format: s.format });
}
}

Expand All @@ -204,9 +210,9 @@ function extractUnwrappedBodyFields(
if (s.readOnly) continue;
if (options?.requiredOnly && !topRequired.includes(key)) continue;
const example = generateExample(s, 0, options);
if (example !== undefined) {
fields.push({ name: key, example, schemaType: s.type, format: s.format });
}
if (example === undefined) continue;
if (isRedundantDefault(s, topRequired.includes(key), example)) continue;
fields.push({ name: key, example, schemaType: s.type, format: s.format });
}

return fields;
Expand All @@ -220,9 +226,14 @@ function extractUnwrappedBodyFields(
if (s.readOnly) continue;
if (options?.requiredOnly && !topRequired.includes(name)) continue;
const example = generateExample(s, 0, options);
if (example !== undefined) {
fields.push({ name, example, schemaType: s.type, format: s.format });
}
if (example === undefined) continue;
if (isRedundantDefault(s, topRequired.includes(name), example)) continue;
fields.push({ name, example, schemaType: s.type, format: s.format });
}
return fields;
}

/** Шум: опциональное поле, у которого пример равен дефолту схемы. Тождественно «не передавать поле». */
function isRedundantDefault(schema: Schema, isRequired: boolean, example: unknown): boolean {
return !isRequired && schema.default !== undefined && example === schema.default;
}
15 changes: 14 additions & 1 deletion apps/docs/lib/openapi/example-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,21 @@ export function generateExample(
}

const propExample = generateExample(ps, depth + 1, options);
const isRequired = requiredFields.includes(propName);

// Шум: опциональное поле, у которого сгенерированный пример равен дефолту,
// — это эквивалент «не передавать поле». Не засоряем им примеры.
if (
!isRequired &&
ps.default !== undefined &&
propExample !== undefined &&
propExample === ps.default
) {
continue;
}

// Включаем свойство если оно обязательное или имеет пример
if (propExample !== undefined || requiredFields.includes(propName)) {
if (propExample !== undefined || isRequired) {
example[propName] = propExample !== undefined ? propExample : null;
}
}
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/public/.well-known/agent-skills/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"type": "skill-md",
"description": "Pachca — управление ботами, вебхуки и превью ссылок. Используй этот скилл, когда пользователь хочет настроить бота, создать бота, настроить вебхуки, обработать вебхук, проверить подпись вебхука (X-Signature), обработать callback нажатия кнопки, создать дайджест-бота или настроить превью ссылок. НЕ для отправки обычных сообщений, показа форм или модальных окон.",
"url": "/.well-known/skills/pachca-bots/SKILL.md",
"digest": "sha256:b04158006849498930d6fdba9448e6b05c09f3fc94ea6cab42b66a0fd22d96a5"
"digest": "sha256:cc703087c03b52896deff06ee4d4d63d4d1bb7ffdd2fde94a16da4563dfca45b"
},
{
"name": "pachca-forms",
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/public/.well-known/skills/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"type": "skill-md",
"description": "Pachca — управление ботами, вебхуки и превью ссылок. Используй этот скилл, когда пользователь хочет настроить бота, создать бота, настроить вебхуки, обработать вебхук, проверить подпись вебхука (X-Signature), обработать callback нажатия кнопки, создать дайджест-бота или настроить превью ссылок. НЕ для отправки обычных сообщений, показа форм или модальных окон.",
"url": "/.well-known/skills/pachca-bots/SKILL.md",
"digest": "sha256:b04158006849498930d6fdba9448e6b05c09f3fc94ea6cab42b66a0fd22d96a5"
"digest": "sha256:cc703087c03b52896deff06ee4d4d63d4d1bb7ffdd2fde94a16da4563dfca45b"
},
{
"name": "pachca-forms",
Expand Down
28 changes: 24 additions & 4 deletions apps/docs/public/.well-known/skills/pachca-bots/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,32 @@ Help: `npx -y @pachca/cli --help` | Workflows: `npx -y @pachca/cli guide`

## Workflows

### Создать бота через API и получить токен

1. Создай бота. Только пользовательским токеном (не токеном бота); `nickname` обязан заканчиваться на `_bot`. Параметры вебхука (Webhook URL, события, команды) можно задать сразу или позже:
```bash
pachca bots create --bot='{"webhook":{"name":"Бот задач","nickname":"tasks_bot"}}'
```

2. Сохрани `access_token` из ответа — он возвращается единственный раз. Повторно получить токен можно только через интерфейс (вкладка «API» настроек бота)

3. В ответе также придёт `id` бота (его `user_id`) — он нужен для дальнейших вызовов, например чтобы добавить бота в чат

> Создавать ботов можно только пользовательским токеном — токеном бота нельзя. `access_token` отдаётся один раз при создании, дальше его можно посмотреть и скопировать в интерфейсе.


### Настроить бота с исходящим вебхуком

1. Создай бота в интерфейсе Пачки: Автоматизации → Интеграции → Webhook
1. Создай бота, сразу указав Webhook URL и события в одном вызове (детали создания и работы с токеном — в сценарии «Создать бота через API и получить токен»):
```bash
pachca bots create --bot='{"webhook":{"name":"Бот задач","nickname":"tasks_bot","outgoing_url":"https://example.com/webhook","events":["message_new"],"trigger_on":"commands","commands":["/task"]}}'
```

2. Получи `access_token` бота во вкладке «API» настроек бота
2. Сохрани `access_token` из ответа (возвращается единственный раз)

3. Укажи Webhook URL для получения событий
3. Используй сохранённый `access_token` для отправки сообщений от имени бота

> Бот создаётся через UI, не через API. Единственный эндпоинт для ботов — PUT /bots/{id} (обновление webhook URL). API используется для отправки сообщений от имени бота.
> Альтернатива — создать и настроить бота в интерфейсе. Webhook URL и события можно задать и позже методом PUT /bots/{id}.


### Обновить Webhook URL бота
Expand Down Expand Up @@ -86,13 +103,16 @@ Help: `npx -y @pachca/cli --help` | Workflows: `npx -y @pachca/cli guide`
## Limitations

- Rate limit: ~50 req/sec. On 429 — wait and retry.
- `bot.webhook.trigger_on`: allowed values — `commands` (Только на команды (триггер-слова) из commands), `all_messages` (На все сообщения в чатах, где есть бот), `unfurl` (На развёртывание ссылок (link previews))
- `limit`: max 50
- Pagination: cursor-based (limit + cursor)

## Endpoints

| Method | Path | Description |
|--------|------|-------------|
| POST | /bots | Создание бота |
| GET | /bots/{id} | Получение бота |
| PUT | /bots/{id} | Редактирование бота |
| POST | /messages/{id}/link_previews | Unfurl (разворачивание ссылок) |
| GET | /webhooks/events | История событий |
Expand Down
Loading
Loading