Перейти к содержанию

Подписки на события (Webhooks)

Система позволяет внешним сервисам (Odoo, боты) получать уведомления о событиях через HTTP-вызовы.

Как подписаться

Создайте подписку, указав URL и список событий. В ответе придёт secret — ключ для проверки подлинности. Сохраните его, повторно получить нельзя.

Паттерны событий

При создании подписки можно указать конкретные события или паттерны:

Паттерн Что получите
property.delisted Только делистинг
property.transition.* Все переходы статусов
property.* Все property-события (создание, переходы, модерация, делистинг)
mls.* Листинг и делистинг с MLS
contact_request.* Запросы контакта через MLS
* Все события

Какие события существуют

Событие Когда срабатывает Что содержит
property.created Создан новый объект property_id, tenant_id
property.transition.{action} Переход статуса (approve, delist, ...) property_id, action, from/to status
property.delisted Объект снят с MLS property_id, tenant_id, from_status_id, from_status_name
property.moderation_required Объект отправлен на проверку (→ in_review) property_id, tenant_id
mls.new_listing Объект появился на MLS (→ approved/assigned) property_id, tenant_id
mls.listing_removed Объект убран с MLS property_id, tenant_id
contact_request.received Кто-то запросил контакт через MLS property_id, requester_tenant_id, owner_tenant_id
tenant.subscription_expiring Подписка тенанта истекает через 7 дней tenant_id, expires_at

Пример payload делистинга

{
  "event_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "event_type": "property.delisted",
  "timestamp": "2026-02-16T12:00:00+00:00",
  "data": {
    "event_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "event_type": "property.delisted",
    "property_id": 40,
    "tenant_id": 1,
    "from_status_id": 3,
    "from_status_name": "legal_check",
    "timestamp": "2026-02-16T12:00:00+00:00"
  }
}

Проверка подлинности (HMAC)

Каждый webhook-вызов подписывается ключом secret из подписки. Заголовок X-EstateKit-Signature содержит подпись sha256=<hex>.

import hashlib, hmac

def verify(body: bytes, secret: str, signature: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature.removeprefix("sha256="))

Заголовки webhook-вызова

Заголовок Описание
X-EstateKit-Event Тип события
X-EstateKit-Signature HMAC-SHA256 подпись
X-EstateKit-Delivery-Id UUID для дедупликации
X-EstateKit-Timestamp Unix timestamp отправки

Повторные попытки

  • При ошибке (HTTP 5xx, timeout, connection error) — повторная доставка
  • Интервалы: 2с, 4с, 8с, 16с, ... до 1 часа (exponential backoff)
  • Максимум 10 попыток
  • После 10 неудач подписка автоматически деактивируется
  • Успех: любой HTTP 2xx ответ

Идемпотентность

Каждое событие содержит уникальный event_id. Клиент должен сохранять обработанные ID и пропускать дубликаты. Заголовок X-EstateKit-Delivery-Id — тот же UUID.

Прямое подключение к RabbitMQ

Альтернатива webhooks — подключение напрямую к RabbitMQ (exchange estate_kit.events, topic). Routing keys:

  • property.created, property.transition.approve, property.delisted
  • mls.new_listing, mls.listing_removed
  • contact_request.received
  • # — все события