For Developers
Examples
Example 1. CRM → SupportHub
A manager logs a customer request in the CRM, and the integration creates a ticket in SupportHub so support sees it alongside everything else.
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()Example 2. An auto-reply over long polling
A bot with no public address pulls events over long polling and answers new customer messages. The reply goes out as the bot: customers see it in the website widget, but it isn’t sent to Telegram, VK, WhatsApp or 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) # new events only
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": "Thanks, we'll get back to you soon!"},
timeout=10,
)Example 3. Events into an internal dashboard
A Node.js service pulls events and hands them to your own dashboard (notifyDashboard is your function).
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);
}
}You can combine the scenarios: one part of your system writes with
POST /api/v1/messages, another receives events through /updates or webhooks. The rate limit covers the whole API and is counted per key: every part of your system that uses one key shares one budget (see Limits & errors).Was this page helpful?

