Tickets
Тикет — обращение клиента. Через API тикеты можно читать, создавать, менять, закрывать и переоткрывать. Удалить тикет через API нельзя.
- Статусы:
new,open,in_progress,pending(отложен),resolved,closed. - Приоритеты:
low,normal,high,urgent. channel_type— канал, из которого пришёл тикет (telegram,widget,email,vk,whatsapp,billmgr…). У тикетов, созданных через API,channel_idиchannel_typeравныnull.
/api/v1/ticketsСписок тикетов
Все тикеты проекта постранично, новые сверху (по дате создания).
Query-параметры:
status,priority— одно из значений выше; другое значение — 422contact_id— UUID контакта, только его тикетыsince— ISO 8601, тикеты, созданные в этот момент или позже. Время со смещением пояса переводится в UTC (13:30+02:00— это 11:30 UTC), время без смещения считается UTCinclude_history—trueдобавляет к каждому тикетуlast_message_preview(первые 100 символов последнего сообщения) иmessage_count; внутренние заметки не учитываютсяpage(по умолчанию 1),page_size(по умолчанию 20, максимум 100)
curl "https://api.support.forestsnet.com/api/v1/tickets?status=open&page_size=10&include_history=true" \
-H "Authorization: Bearer sk_xxx"{
"items": [
{
"id": "8a3f...",
"workspace_id": "1c2b...",
"contact_id": "44e1...",
"channel_id": "c7d0...",
"channel_type": "widget",
"assigned_to": null,
"department_id": null,
"subject": "Не приходит код подтверждения",
"status": "open",
"priority": "normal",
"tags": ["billing"],
"first_response_at": null,
"resolved_at": null,
"closed_at": null,
"rating": null,
"created_at": "2026-04-06T10:12:33.123456",
"updated_at": "2026-04-06T10:12:33.123456",
"last_message_preview": "Здравствуйте, не приходит код",
"message_count": 4
}
],
"total": 137,
"page": 1,
"page_size": 10
}/api/v1/tickets/{ticket_id}Тикет с последними сообщениями
Возвращает тикет, его последние сообщения (по порядку, старые сверху) и контакт. Внутренние заметки операторов тоже входят в список — у них is_internal: true. Формат сообщения — на странице Messages.
Query-параметры:
last_messages— сколько последних сообщений вернуть (1–200, по умолчанию 20)
curl "https://api.support.forestsnet.com/api/v1/tickets/8a3f...?last_messages=50" \
-H "Authorization: Bearer sk_xxx"{
"ticket": { "id": "8a3f...", "status": "open", ... },
"messages": [ { "id": "f1...", "sender_type": "contact", "content": "Здравствуйте", ... } ],
"contact": { "id": "44e1...", "full_name": "Иван", "email": "ivan@example.com", ... }
}/api/v1/ticketsСоздать тикет
Всегда создаёт новый тикет, даже если у контакта уже есть открытый. Контакт ищется по telegram_id, затем по email; если не найден — создаётся. В contact обязателен хотя бы один из них, имя можно передать в name или full_name (оно обновит имя найденного контакта).
contact— обязательно:telegram_id(число) и/илиemail, плюсnamemessage— текст первого сообщения; сохраняется как сообщение клиентаsubject— тема; если не задана, берутся первые 120 символовmessagepriority— по умолчаниюnormaltags— массив строк
{
"subject": "Не работает оплата",
"priority": "high",
"tags": ["billing", "vip"],
"contact": {
"email": "ivan@example.com",
"name": "Иван Петров"
},
"message": "Пытаюсь оплатить тариф, получаю ошибку 500."
}curl -X POST https://api.support.forestsnet.com/api/v1/tickets \
-H "Authorization: Bearer sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"priority": "high",
"contact": {"email": "ivan@example.com", "name": "Иван"},
"message": "Не приходит код"
}'Ответ — 201 и объект тикета (как в списке, без полей истории) со статусом new. Ошибки: 400 без telegram_id и email, 422 при неизвестном priority, 403 TICKET_LIMIT_REACHED при исчерпанном месячном лимите тикетов, 403 для заблокированного контакта.
/api/v1/tickets/{ticket_id}Изменить тикет
Меняет status, priority, tags (список заменяется целиком) и subject. Передавайте только нужные поля; null значение не меняет. Неизвестный status или priority — 422, тикет не меняется.
{ "priority": "urgent", "tags": ["vip", "p1"] }ticket.updated (ticket_id, workspace_id). Он не ставит closed_at и не отправляет клиенту сообщение о закрытии. Смена статуса видна в /updates как ticket.status_change. Чтобы закрыть или переоткрыть тикет, используйте эндпоинты ниже./api/v1/tickets/{ticket_id}/closeЗакрыть тикет
Ставит статус closed и closed_at (и resolved_at, если его ещё не было), фиксирует SLA решения, публикует в переписке системное сообщение о закрытии и отправляет его клиенту в его канал. Шлёт webhook ticket.closed. Уже закрытый тикет — 409 TICKET_ALREADY_CLOSED. Ответ — объект тикета.
Закрытие через API — действие вашей стороны, поэтому клиент читает, что обращение закрыла поддержка, без имени оператора: «🔒 Обращение закрыто оператором» или «🔒 Conversation closed» — на языке клиента (язык виджета, затем язык контакта, затем язык проекта по умолчанию). В тикетах из виджета используется текст «Тикет закрыт» из конструктора виджета, если он задан; если это сообщение там выключено, его нет. Если для канала включены оценки, клиенту приходит просьба оценить обращение.
/api/v1/tickets/{ticket_id}/reopenПереоткрыть тикет
Работает только для тикетов в статусе closed или resolved, иначе — 422 TICKET_INVALID_STATUS_TRANSITION. Ставит статус open, очищает closed_at, resolved_at и first_response_at, перезапускает SLA. Клиент получает уведомление, если оно включено в настройках канала. Шлёт webhook ticket.reopened.
Ещё о тикетах: история обращений контакта, оценка тикета.

