API шахматки: версия, дельты и вебхуки
Интеграция для тех, кому нужна не готовая вставка, а свои страницы. Данные отдаются так, чтобы их не приходилось выкачивать целиком: короткая версия, снимок с ETag, дельты и события на ваш адрес.
Ключ создаётся в панели за минуту, авторизация для чтения не нужна
Ключ и домен канала
Ключ dxp_… открывает только ЖК канала, а запрос не с разрешённого домена получит 403.
Версия — сотни байт
Хэш версии и счётчики по статусам: видно, изменилось ли что-то, без каталога.
ETag снимка
Адрес снимка из snapshotUrl содержит версию и кэшируется навсегда; ETag возвращайте как есть, с W/.
304 без тела
Ничего не изменилось — ответ пустой, трафика почти нет.
Правка в панели
Менеджер сохранил бронь и новую цену №32 — ревизия ЖК выросла до 12.
С вашей ревизии
since=ЖК:ревизия; для канала с одним ЖК хватит числа.
Только изменившееся
В items — изменённые квартиры в том же виде, что в снимке.
Удалённые отдельно
deleted — что убрать с сайта; если ревизия уже забыта, придёт fullRequired.
Событие на ваш адрес
complex.changed несёт новую и прежнюю ревизию — дельту можно брать сразу.
Подпись HMAC-SHA256
От «метка времени.тело» на секрете whs_…, который показывается один раз.
Проверка одной строкой
Подпись совпала — отвечайте 2xx; запросы старше пяти минут отклоняйте.
Журнал и повторы
Повторы через 1, 5, 30, 120 и 360 минут; после 20 неудач подряд подписка выключается.
Как это работает
Как встроить за один вечер
Создайте канал
Раздел «Публикация» → канал с типом «виджет»: он даёт публичный ключ и список разрешённых доменов.
Спросите версию
GET /version — хэш шахматки и счётчики по каждому ЖК. Дёшево настолько, что можно звать часто.
Заберите снимок
GET /apartments с профилем short или full. Ответ кэшируется и проверяется по ETag.
Подпишитесь на события
Вебхук с подписью HMAC приходит при изменении цен, статусов и состава квартир.
Преимущества
Что сделано ради вашего трафика
Версия вместо каталога
Проверка изменений — несколько сотен байт. Не нужно качать тысячу квартир, чтобы понять, что не поменялось ничего.
ETag и 304
Адрес снимка из snapshotUrl содержит версию и не меняется — кэш на стороне клиента и CDN. Повтор с ETag в If-None-Match стоит одного заголовка.
Дельты по ревизии
?since=1234567:11 вернёт только изменившиеся и удалённые квартиры. Журнал изменений ведут триггеры базы, а не приложение.
Вебхуки с подписью
HMAC-SHA256 по строке «метка времени.тело», в заголовке с префиксом sha256=. Повторы 1/5/30/120/360 минут, автоотключение после 20 неудач подряд.
CORS без фокусов
Публичные ручки отвечают Allow-Origin: * и отдают ETag наружу, поэтому запрос можно делать прямо из браузера.
Контракт версии 1
Поля публичного ответа отделены от внутренних: переименование колонки в панели не ломает ваш код.
Чем это отличается от выгрузки XML
XML-фид — формат для площадок: он собирается по расписанию, содержит объявления целиком и не умеет отвечать на вопрос «что изменилось с прошлого раза». Для сайта это неудобно: чтобы показать актуальные цены, приходится либо скачивать фид целиком, либо мириться с задержкой.
Публичное API устроено под инкрементальное обновление. Версия шахматки меняется, только когда действительно поменялись данные ЖК: за этим следят триггеры в базе, а не ручные вызовы из кода. Поэтому клиент может спрашивать версию хоть каждую минуту и почти всегда получать «ничего не изменилось» за сотни байт.
Каналами можно управлять не только руками: те же настройки доступны по API и через MCP — нейросеть создаёт канал, меняет оформление и показывает предпросмотр. Публикация при этом остаётся отдельным разрешением, которое выдаётся ключу осознанно.
Что отдаёт API
- Версию шахматки и счётчики по статусам
- Снимок квартир: профиль short или full
- Дельты изменений от известной ревизии
- Карточку ЖК: адрес, класс, сроки, инфраструктуру
- Планировки, фото и виды из окна
- Скидки и акции по квартирам
- Приём заявок с вашей формы в CRM
- События на ваш адрес: цены, статусы, заявки
Примеры
Три запроса, которые всё решают
Сначала спрашиваем версию — это несколько сотен байт. Если version совпал с сохранённым у вас, дальше идти некуда. Браузер сам присылает заголовок Origin, а в curl его нужно передать: если у канала задан список доменов, запрос без Origin и Referer получит 403:
curl https://domxml.ru/api/public/v1/$KEY/version \
-H 'Origin: https://ваш-сайт.ru'
# {"contract":"1","version":"0da94d56a6ca41f2","complexes":[
# {"complexId":5627431,"rev":12,"apartments":{"total":50,"available":37}}],
# "snapshotUrl":"/api/public/v1/dxp_…/apartments?v=0da94d56a6ca41f2"}
Изменилось — забираем снимок по snapshotUrl из ответа. В адресе — версия, содержимое по нему уже не изменится, поэтому он отдаётся с immutable: браузер и CDN второй раз его не скачают. Есть и ETag — верните его в If-None-Match как есть, вместе с W/, если сервер сжал ответ, и при той же версии придёт 304 без тела:
curl -i "https://domxml.ru/api/public/v1/$KEY/apartments?v=0da94d56a6ca41f2" \
-H 'Origin: https://ваш-сайт.ru'
# HTTP/2 200
# cache-control: public, max-age=31536000, immutable
# etag: W/"v1-dxp_…-0da94d56a6ca41f2-short"
curl -i "https://domxml.ru/api/public/v1/$KEY/apartments?v=0da94d56a6ca41f2" \
-H 'Origin: https://ваш-сайт.ru' \
-H 'If-None-Match: W/"v1-dxp_…-0da94d56a6ca41f2-short"'
# HTTP/2 304
Если у вас уже есть прошлый снимок, весь каталог качать незачем — спрашиваем дельту от известной ревизии:
curl "https://domxml.ru/api/public/v1/$KEY/changes?since=5627431:11" \
-H 'Origin: https://ваш-сайт.ru'
# {"contract":"1","version":"0da94d56a6ca41f2","complexes":[{
# "complexId":5627431,"rev":12,"since":11,"changed":true,
# "items":[{"id":812,"price":8990000.0,"status":"reserved"}],"deleted":[]}]}
Ответ приходит по каждому ЖК отдельно: items — изменившиеся квартиры, deleted — удалённые. Если журнал не помнит вашу ревизию, придёт fullRequired — тогда забирайте снимок целиком.
А чтобы не опрашивать вовсе — подпишитесь на события. Подпись приходит в заголовке X-DomXML-Signature с префиксом sha256=, проверяют её так:
const signed = `${req.headers['x-domxml-timestamp']}.${rawBody}`;
const mine = 'sha256=' + crypto.createHmac('sha256', secret).update(signed).digest('hex');
if (mine !== req.headers['x-domxml-signature']) return res.sendStatus(401);
FAQ
Частые вопросы
Как часто можно опрашивать API?
Ограничение — 240 запросов в минуту с одного адреса и 1200 на канал. Этого хватает с запасом: правильный цикл спрашивает версию раз в минуту и идёт за данными, только когда хэш изменился.
Зачем дельты, если есть снимок?
Снимок ЖК на тысячу квартир — это сотни килобайт, а типичное изменение за день — несколько лотов. Дельта возвращает только их, поэтому обновление стоит трафика меньше, чем одна фотография.
Как проверить подпись вебхука?
Считайте HMAC-SHA256 от строки «метка времени, точка, тело запроса» на своём секрете, добавьте спереди «sha256=» и сравните с заголовком X-DomXML-Signature. Секрет показывается один раз при создании подписки.
Нужен ли ключ и что он открывает?
Для чтения — только публичный ключ канала: он открывает ровно те ЖК, которые вы в этот канал добавили. Для управления каналами нужен API-ключ с отдельным разрешением «Управление витриной и виджетами».
Что будет, если я удалю канал?
Ключ перестанет отвечать: и вставка на сайте, и ваши запросы получат 404. По ключу нельзя отличить «канала не было» от «канал выключен» — это сделано специально.
Заберите данные к себе на сайт
Создайте канал, скопируйте ключ и сделайте первый запрос — API бесплатное
Начать бесплатно