Payload format
HTTP request
Каждое delivery — POST на webhook URL с JSON-телом и заголовками:
POST /webhook HTTP/1.1
Host: yourbot.com
User-Agent: ReasonspaceBotWebhook/1.0
Content-Type: application/json
X-Reasonspace-Event: message.created
X-Reasonspace-Delivery: deedccc1-dd21-4a6a-b342-f2bd83596810
X-Reasonspace-Signature: t=1748340000,v1=4f3e9c8d2a1b5e7f...
{
"id": "deedccc1-...",
"type": "message.created",
"space_id": "019bfa33-...",
"delivered_at": "2026-05-27T10:07:14Z",
"bot_user_id": "e8e311f6-...",
"data": { ... }
}
Headers reference
User-AgentВсегда ReasonspaceBotWebhook/1.0. Stable, не меняется без deprecation.
X-Reasonspace-Eventevent_type, дублирует payload.type. Удобно для router'а в коде бота
без парсинга body.
X-Reasonspace-DeliveryUUID delivery (= payload.id). Для idempotency.
X-Reasonspace-SignatureHMAC-SHA256 (Stripe-style). См. Signing.
Body fields
idUUIDУникальный delivery id. Один event может прилететь несколько раз
(retry) — id остаётся тем же.
typestringevent-type. См. Каталог.
space_idUUID | nullSpace, где произошло событие. null для глобальных.
delivered_atISO 8601 timestampМомент, когда dispatcher положил event в очередь. Может отличаться от
момента события (data.created_at для message.created) на ~миллисекунды.
bot_user_idUUIDID самого бота (= is_bot=true user). Удобно при наличии нескольких
ботов через один webhook receiver.
dataobjectEvent-specific payload. См. Каталог per event-type.
Размер payload'а
Обычно меньше 2 KB. Размер зависит от события: payload с data.content
(например, message.created с длинным текстом) больше, чем
member/voice/lifecycle-события без тела. Webhook URL должен accept body
хотя бы до 100 KB.
Кодировка
Тело кодируется в UTF-8 (ensure_ascii=False); заголовок —
Content-Type: application/json без параметра charset. Тело — компактный
JSON без pretty-print (parser должен accept любой valid JSON).
Ответ от бота
Endpoint бота должен вернуть 2xx за ≤ 10 секунд. Иначе delivery
считается timeout'ом и идёт в retry.
HTTP/1.1 200 OK
Content-Type: application/json
{"ok": true}
Тело ответа игнорируется платформой. Главное — статус-код.
Не блокировать на handle. Если обработка > 1 секунды (например, длительная подготовка контента) — возвращайте 200 сразу, а саму работу выполняйте асинхронно (фоновая задача / очередь на стороне бота).