Для разработчиков
Примеры использования
Пример 1. CRM → SupportHub
Менеджер в CRM заводит обращение клиента — интеграция создаёт тикет в SupportHub, чтобы поддержка увидела его в общем интерфейсе.
crm_to_supporthub.py
import requests
def create_support_ticket(crm_user, text):
requests.post(
"https://api.support.forestsnet.com/api/v1/tickets",
headers={"Authorization": "Bearer sk_xxx"},
json={
"subject": text[:80],
"priority": "normal",
"tags": ["from-crm"],
"contact": {
"email": crm_user.email,
"name": crm_user.full_name,
},
"message": text,
},
timeout=10,
).raise_for_status()Пример 2. Автоответ через long polling
Бот без публичного адреса забирает события через long polling и отвечает на новые сообщения клиентов. Ответ уходит от имени бота: клиент увидит его в виджете на сайте, а в Telegram, VK, WhatsApp и на email он не отправляется.
bot.py
import time
import requests
API = "https://api.support.forestsnet.com/api/v1"
HEAD = {"Authorization": "Bearer sk_xxx"}
offset = int(time.time() * 1_000_000) # только новые события
while True:
r = requests.get(
f"{API}/updates",
headers=HEAD,
params={"offset": offset, "timeout": 25, "types": "message.created"},
timeout=35,
)
if r.status_code != 200:
time.sleep(5)
continue
for ev in r.json()["updates"]:
offset = max(offset, ev["id"])
msg = ev["data"]
if msg["sender_type"] != "contact":
continue
requests.post(
f"{API}/tickets/{msg['ticket_id']}/messages",
headers=HEAD,
json={"content": "Спасибо, скоро ответим!"},
timeout=10,
)Пример 3. События во внутренний дашборд
Сервис на Node.js забирает события и передаёт их в свой дашборд (notifyDashboard — ваша функция).
dashboard-bridge.mjs
const API = "https://api.support.forestsnet.com/api/v1";
const HEAD = { Authorization: "Bearer sk_xxx" };
let offset = Date.now() * 1000;
while (true) {
const url = new URL(API + "/updates");
url.searchParams.set("offset", String(offset));
url.searchParams.set("timeout", "25");
url.searchParams.set("types", "ticket.created,message.created");
const r = await fetch(url, { headers: HEAD });
if (!r.ok) {
await new Promise((resolve) => setTimeout(resolve, 5000));
continue;
}
const { updates } = await r.json();
for (const ev of updates) {
if (ev.id > offset) offset = ev.id;
if (ev.type === "ticket.created") notifyDashboard("new_ticket", ev.data.ticket);
if (ev.type === "message.created" && !ev.data.is_internal) notifyDashboard("new_message", ev.data);
}
}Сценарии можно совмещать: одна часть системы пишет через
POST /api/v1/messages, другая получает события через /updates или webhooks. Лимит запросов общий для всего API и считается по ключу: все части системы с одним ключом делят один бюджет (см. Лимиты и ошибки).Была ли страница полезной?

