Airtable x GREEN-API - разработка собственной интеграции#
Данная интеграция позволяет отправлять сообщения WhatsApp*, Telegram и MAX из базы Airtable и получать ответы обратно в базу через платформу GREEN-API. Разработана на базе Universal Integration Platform от GREEN-API и состоит из двух частей, которые находятся в одном репозитории: расширения Airtable (extension/) и сервиса-адаптера (src/).
Содержание#
- Обзор
- Архитектура
- Установка
- Как работает интеграция
- API адаптера
- Какие данные хранит адаптер
- Разработка и тесты
- Лицензия
Обзор#
Данная документация проведет вас через процесс развертывания собственной копии интеграции между GREEN-API и Airtable. Вы:
- Развернёте сервис-адаптер на публичном домене с HTTPS и базой данных MySQL.
- Зарегистрируете собственную OAuth-интеграцию Airtable с адресом перенаправления на вашем домене и укажете её client id и client secret в
.env. - Создадите собственное расширение (custom extension) в базе Airtable и подключите к нему проект
extension/. - Откроете расширение, в
Settings→Advancedукажете адрес вашего адаптера, подтвердите личность и добавите инстансы.
Работа с интеграцией после установки - подтверждение личности, права участников по ролям, отправка и приём сообщений - описана в разделе Подключение интеграции. Ниже описано только то, что нужно для развёртывания и доработки своей копии.
Архитектура#
Airtable base ──(extension UI)──▶ adapter ──▶ GREEN-API ──▶ WhatsApp / Telegram / MAX
▲ │
└──(Airtable Web API, OAuth)───┘◀── webhooks (messages, statuses) ◀── GREEN-API
Расширение Airtable#
Расширение на Blocks SDK, которое:
- Хранит настройки базы: сопоставление таблиц и полей, настройки отправки
- Формирует сообщение для каждой строки и показывает предпросмотр
- Передаёт пакет сообщений в адаптер и показывает результат по каждой строке
- Хранит персональный ключ участника в локальном хранилище браузера
Сервис-адаптер#
Приложение NestJS, которое:
- Хранит учётные данные инстансов GREEN-API. В базе Airtable секреты не хранятся
- Подтверждает личность участников через Airtable OAuth, проверяет их роль в базе и выдаёт персональные ключи
- Отправляет сообщения через GREEN-API и возвращает результат по каждой строке
- Принимает вебхуки GREEN-API и записывает входящие и исходящие сообщения и статусы в базу через Airtable Web API
Установка#
Минимальные требования#
- Node.js 24
- База данных MySQL 8 (или MariaDB)
- Публичный HTTPS-адрес для адаптера - на него приходят вебхуки GREEN-API и перенаправления OAuth
- Аккаунт и инстанс(ы) GREEN-API
- Платный тариф Airtable - собственные расширения и Marketplace доступны только на платных тарифах
Регистрация OAuth-интеграции в Airtable#
На странице airtable.com/create/oauth:
-
Задайте название и зарегистрируйте интеграцию.
-
Сгенерируйте client secret (
Generate a client secret). Обмен токенов выполняет адаптер, то есть сервер, поэтому Airtable требует секрет. Скопируйте секрет в.env. -
Укажите OAuth redirect URL:
<APP_URL>/api/v1/oauth/callback. -
Выберите scopes - ровно эти четыре:
Scope Для чего используется user.email:readопределение участника при подтверждении личности schema.bases:readчтение роли участника в базе, названий таблиц и полей для приёма сообщений data.records:readпоиск контакта, с которым нужно связать входящее сообщение data.records:writeзапись строк сообщений и статусов
Адаптер всегда использует PKCE (этого требует Airtable). Client secret передаётся в заголовке HTTP Basic при запросах получения и обновления токена. Токены доступа действуют 60 минут, адаптер обновляет их сам. Refresh-токены действуют 60 дней и продлеваются при каждом использовании.
Настройка адаптера#
1. Клонируйте репозиторий:
```bash
git clone https://github.com/green-api/greenapi-integration-airtable.git
cd greenapi-integration-airtable
```
-
Установите зависимости:
npm ci -
Настройте переменные окружения:
cp .env.example .envЗаполните в
.envследующие переменные:Переменная Значение DATABASE_URLстрока подключения к MySQL, например mysql://user:pass@host:3306/adapterAPP_URLпубличный адрес адаптера, например https://your-adapter-domain.com. Из него строятся адрес перенаправления OAuth (/api/v1/oauth/callback) и адрес вебхуков (/api/v1/webhooks/green-api)PORTпорт, по умолчанию 3000AIRTABLE_CLIENT_IDclient id OAuth-интеграции Airtable (шаг выше) AIRTABLE_CLIENT_SECRETclient secret той же интеграции. Обязательная переменная: без неё адаптер не запустится Все переменные проверяются при запуске адаптера.
-
Примените миграции базы данных:
npx prisma migrate deploy -
Соберите и запустите адаптер:
# Сборка приложения npm run build # Запуск в production режиме npm run start:prod
Развертывание в Docker#
В корне репозитория есть Dockerfile и docker-compose.yml. Для запуска выполните:
docker compose up --build
Команда применяет миграции базы данных, а затем запускает адаптер.
Запуск и выпуск расширения#
Каталог extension/ - стандартный проект Blocks SDK, уже инициализированный. Создайте расширение в базе и запустите его в режиме разработки по инструкции Установка расширения в базу. При разработке учитывайте:
- файл
extension/.block/remote.jsonу каждого разработчика свой и не попадает в git; - скрипты
npm start,npm run releaseиnpm run submitвextension/package.jsonзапускают Blocks CLI фиксированной версии (@airtable/blocks-cli@3.0.3) черезnpx, поэтомуnpm startможно использовать вместоblock run; - dev-сервер пересобирает панель при каждом изменении кода;
- после запуска укажите в расширении адрес вашего адаптера:
Settings→Advanced. Адрес по умолчанию задан константойDEFAULT_ADAPTER_URLвextension/frontend/defaults.ts.
Для публикации:
npm run release # block release - выпускает сборку в расширение базы
npm run submit # block submit - отправка на проверку в Marketplace
Собственное расширение работает в одной базе. Чтобы использовать его в другой базе, добавьте её как ещё один remote (block add-remote) и выполните выпуск снова.
Как работает интеграция#
Отправка сообщений#
- Расширение формирует сообщение для каждой строки и передаёт пакет в адаптер (
POST jobs). Типы сообщений и ограничения по мессенджерам описаны в разделе Типы сообщений. - Адаптер не делает пауз между сообщениями - интервал задаёт очередь GREEN-API, параметр
delaySendMessagesMillisecondsв настройках инстанса. - Файлы отправляются загрузкой: когда адаптер доходит до строки, он скачивает вложение и загружает его в GREEN-API методом
sendFileByUpload.
Отправку без панели расширения - из автоматизаций Airtable и внешних сервисов - выполняет маршрут POST send с ключом для автоматизаций. Формат запроса и ответа описан в разделе Отправка из автоматизаций Airtable и других сервисов.
Приём сообщений#
- Для записи в базу адаптеру нужен доступ Airtable OAuth с
data.records:read/writeиschema.bases:read. Первое подтверждение личности владельца уже включает этот доступ. - При включении приёма для инстанса адаптер вызывает
setSettingsсwebhookUrl = <APP_URL>/api/v1/webhooks/green-apiи случайнымwebhookUrlToken. При выключении приёма адрес вебхуков очищается. - Адаптер записывает каждый вебхук в Airtable синхронно и отвечает GREEN-API кодом
200. Если запись не удалась (ограничение Airtable на число запросов, истёкший токен, удалённое поле, сбой Airtable), адаптер отвечает503, и GREEN-API повторяет доставку того же вебхука. - Повторно доставленное сообщение, которое уже записано, распознаётся по
idMessageи не дублируется.
Что видит владелец базы при настройке приёма и как обновляются статусы, описано в разделе Приём входящих сообщений.
Номера телефонов и ID чатов#
Как расширение распознаёт номера телефонов, ID чатов и ID групп, описано в разделе Номера телефонов и ID чатов. При отправке номер телефона приводится к виду <цифры>@c.us: в WhatsApp - любое значение, кроме ID группы (…@g.us), в Telegram и MAX - только значение, записанное как номер телефона.
Методы GREEN-API#
Что делает каждый инструмент, описано в разделе Дополнительные инструменты. Ниже указано, какие методы GREEN-API он вызывает.
| Где в расширении | Метод GREEN-API |
|---|---|
Tools → Check numbers | checkWhatsapp / checkAccount |
Tools → Chat history | checkAccount, getChatHistory. Для Telegram и MAX номер телефона сначала преобразуется в ID чата, потому что их журналы ведутся по ID чата |
Tools → Import history | lastIncomingMessages, lastOutgoingMessages |
Tools → Import contacts | getContacts |
Instances → Link phone | qr |
Вкладка Send, очередь сообщений | showMessagesQueue, clearMessagesQueue |
Ссылки ведут на описание методов для WhatsApp.
API адаптера#
Все маршруты находятся под /api/v1. Каждый маршрут, кроме oauth/* и webhooks/*, требует заголовок Authorization: Bearer pk_… (персональный ключ). Ограничения: 300 запросов в минуту с одного IP; для oauth/identity - 10 в минуту.
| Метод | Маршрут | Кто | Назначение |
|---|---|---|---|
| POST | oauth/identity | любой | начать подтверждение личности для базы → адрес авторизации |
| POST | oauth/claim | любой | обменять завершённую авторизацию на персональный ключ |
| GET | oauth/callback | Airtable | адрес перенаправления OAuth |
| POST | oauth/base | владелец | (повторно) дать адаптеру доступ Airtable к базе |
| GET | bases/me | участник | данные базы: подключение Airtable, настройки приёма, инстансы, текущий пользователь |
| PUT / DELETE | bases/inbound | владелец | задать / удалить настройки приёма |
| DELETE | bases/airtable | владелец | отключить доступ Airtable к базе |
| GET | instances | участник | инстансы с текущим состоянием и номером |
| POST | instances | владелец | добавить инстанс (idInstance, apiTokenInstance, apiUrl, name?) |
| PATCH | instances/:id/receive | владелец | включить / выключить приём |
| DELETE | instances/:id | владелец | удалить инстанс (сначала очищает его вебхук) |
| GET | users/me, users | участник / владелец | текущий пользователь; все, кто подтвердил личность |
| PUT | users/:id/instances | владелец | какие инстансы доступны редактору |
| POST | users/:id/revoke, DELETE users/:id | владелец | отозвать ключ / удалить пользователя |
| POST | jobs | участник | отправить пакет (idInstance, items[], writeBack?) |
| GET | jobs, jobs/:id | участник | последние задания; одно задание с результатами по строкам |
| POST | jobs/:id/cancel | участник | остановить выполняемое задание |
| GET / POST | automation-keys | владелец | список / создание ключей для автоматизаций (сам ключ возвращается один раз) |
| DELETE | automation-keys/:id | владелец | отозвать ключ |
| POST | instances/:id/check | участник | проверить номера в мессенджере инстанса |
| POST | instances/:id/history, instances/:id/chat-history | участник | загрузить журнал / один чат в таблицу сообщений |
| GET | instances/:id/queue, POST instances/:id/queue/clear | участник | размер очереди GREEN-API; очистка очереди |
| GET | instances/:id/qr | участник | QR-код для привязки |
| GET | instances/:id/contacts | участник | контакты мессенджера |
| POST | send | ключ для автоматизаций | отправить одно сообщение и дождаться результата (формат) |
| POST | webhooks/green-api | GREEN-API | приём вебхуков (Bearer webhookUrlToken) |
Какие данные хранит адаптер#
Содержимое сообщений не хранится. В базе данных адаптера находятся:
- ID базы Airtable, её настройки приёма и OAuth-токены Airtable для базы;
- участники, подтвердившие личность: ID пользователя Airtable, email, имя, роль, хеш персонального ключа, а также инстансы, доступные редакторам;
- инстансы:
idInstance,apiTokenInstance,apiUrl, мессенджер, состояние, настройки вебхуков; - ключи для автоматизаций: название, ограничение по инстансу, хеш ключа, время последнего использования;
- задания на отправку: по одной строке на пакет и на каждого получателя со статусом, ID сообщения GREEN-API и ошибкой. Содержимое сообщения хранится, только пока строка стоит в очереди, и удаляется сразу после отправки или ошибки.
Входящие вебхуки сразу записываются в Airtable и не хранятся. Буфером для повторов служит очередь GREEN-API.
Логи адаптера
Библиотека greenapi-integration записывает тела запросов и вебхуков в лог на уровне info. Поэтому текст сообщений и номера телефонов попадают в stdout адаптера, если вывод логов не фильтруется.
Разработка и тесты#
npm test # unit-тесты адаптера (jest)
cd extension && npm test # unit-тесты расширения
- Адаптер: NestJS 11, Prisma 7 (
prisma/schema.prisma), все константы - вsrc/defaults.ts, коды ошибок - вsrc/errors.ts. - Расширение: React 16 и Blocks SDK 1.19. Настройки хранятся в
globalConfigпод ключомgreenapi(extension/frontend/config), формирование сообщений - вextension/frontend/send/compose.ts, стили - вextension/frontend/style.css.
Лицензия#
Лицензировано в соответствии с MIT