Быстрый старт за 1 минуту
Вставьте код туда, где должна быть карта. Вместо dom-na-yamskoy — адрес вашего проекта: он есть в кабинете («Опубликовать» → «Код для сайта» → «JS API», там же готовый код). Карта рядом — ровно этот код.
<div id="kinjo-map" style="height:600px"></div>
<script src="https://map.kinjo.ru/widget.js"></script>
<script>
const map = Kinjo.mount('#kinjo-map', { project: 'dom-na-yamskoy' });
map.on('houseSelect', (house) => console.log(house?.name, house?.sales?.priceText));
</script>Старый код с data-атрибутами работает и дальше. Тот же объект карты у него — Kinjo.mount(элемент).
<div data-kinjo data-project="dom-na-yamskoy" data-controls="-time,-header"></div>
<script src="https://map.kinjo.ru/widget.js" async></script>Цены и квартиры у корпуса — передайте JSON
В карточке корпуса — «от 5,2 млн ₽», «10 квартир в продаже», примечание, свои строки и кнопка на выдачу квартир этого корпуса на вашем сайте (новая вкладка, utm_source=kinjo). Данные передаёт ваш сайт при встраивании: они остаются на странице и на наш сервер не уходят. Измените JSON и нажмите «Применить» — карточка на карте рядом обновится.
Kinjo.mount('#kinjo-map', {
project: 'dom-na-yamskoy',
houses: {
"Корпус 1": {
"priceFrom": 5200000,
"flatsOnSale": 10,
"url": "https://kinjo.ru/",
"note": "Скидка 5% до 31.10",
"button": "Выбрать квартиру",
"lines": [
{
"label": "Сдача",
"value": "IV кв. 2026"
},
{
"label": "Отделка",
"value": "White box"
}
]
},
"Корпус 2": {
"priceFrom": 7850000,
"flatsOnSale": 4
}
},
});| Поле | Что это |
|---|---|
priceFrom | «Цена от», ₽: число или строка «5 200 000» → «от 5,2 млн ₽» |
flatsOnSale | квартир в продаже, целое → «10 квартир в продаже» |
url | ссылка «Смотреть квартиры», только https |
note | примечание под ценой, до 200 знаков |
button | подпись кнопки, до 40 знаков |
lines | свои строки, до 6: [{ label, value }] |
Ключ — ID дома из кабинета (k1) или название ('Корпус 1'). Всё необязательно; что не передано — не показываем. Данные со страницы главнее заполненного в кабинете, null убирает поле кабинета. Всё выводится текстом, не HTML; неподходящее (http-ссылка, лишнее поле) пропускается с предупреждением в консоли.

Без своего JavaScript
JSON — прямо внутри блока карты, например, из шаблона CMS:
<div data-kinjo data-project="dom-na-yamskoy">
<script type="application/json" data-kinjo-houses>
{ "Корпус 1": { "priceFrom": 5200000, "flatsOnSale": 10, "url": "https://ваш-сайт.ru/flats?k=1" } }
</script>
</div>
<script src="https://map.kinjo.ru/widget.js" async></script>На лету
// сайт сам взял цены из своей CRM — передаёт карте на лету
const prices = await fetch('/api/my-prices').then((r) => r.json());
await map.setHouses({
k1: { priceFrom: prices.k1.min, flatsOnSale: prices.k1.count },
k2: { priceFrom: prices.k2.min, flatsOnSale: prices.k2.count },
});Свой iframe — Kinjo.connect(iframe).setHouses({...}). В событии houseSelect приходит итог: house.sales.priceText, flatsText, note, lines.
Страница квартиры
Рядом с планировкой — дом квартиры в ЖК: только сам ЖК с подсвеченным домом, без мест, категорий, солнца, шапки и карточек. Камера сама встаёт так, чтобы дом был в центре и целиком и его не заслоняли соседи. Карту можно вращать и приближать: на компьютере — мышью (колесо — с Ctrl или ⌘), на телефоне — двумя пальцами. Грузится быстро: места, маршруты и зоны в этом режиме не загружаются; на слабом телефоне — 2D с подсветкой.
Кнопка «Открыть карту» в углу открывает полную карту поверх страницы: все элементы, тот же дом выбран, его карточка открыта (с ценами из houses, если вы их передали). Закрыть — ✕, Esc, «назад» или свайп вниз; фокус вернётся на кнопку. Попробуйте:
<div id="flat-map" style="height:420px"></div>
<script src="https://map.kinjo.ru/widget.js"></script>
<script>
Kinjo.mount('#flat-map', {
project: 'dom-na-yamskoy',
house: 'Корпус 2', // дом квартиры: ID, название или подпись
view: 'house',
});
</script><div data-kinjo data-project="dom-na-yamskoy" data-house="Корпус 2" data-view="house"
data-open-label="Дом на карте" style="height:420px"></div>
<script src="https://map.kinjo.ru/widget.js" async></script>Дом — как в selectHouse: ID из кабинета, ID части, название или подпись. section (data-section) подсветит секцию или подъезд, если дом в модели из частей. openLabel (data-open-label) — своя подпись кнопки, false ("0") — без неё. Высота — у блока, без неё — 420 px. Цены и квартиры (houses, data-kinjo-houses) передаются и в полную карту. События mapOpen и mapClose — когда карту открыли и закрыли.
<iframe src="https://map.kinjo.ru/?project=dom-na-yamskoy&house=%D0%9A%D0%BE%D1%80%D0%BF%D1%83%D1%81%202&view=house&embed=1"
style="width:100%;height:420px;border:0" title="Дом на карте ЖК"></iframe>Без widget.js кнопка открывает полную карту в новой вкладке (данные houses туда не попадут — их передаёт widget.js). Ключи API не нужны.
Параметры
Kinjo.mount(el, options) — el элемент или селектор. Возвращает объект карты: методы-обещания и события.
| Параметр | Значения | По умолчанию |
|---|---|---|
project | адрес проекта (slug), обязателен | — |
theme | 'light', 'dark', 'mono', 'warm', 'brand' | как в проекте |
mode | '2d' — быстрее, '3d' — солнце и тени | как в проекте |
layout | 'dock', 'sidebar', 'sidebar:theme' | как в проекте |
dock | 'icons', 'legend' — категории на компьютере | как в проекте |
logo | 'full', 'logo', 'none' — шапка | как в проекте |
isochrones | [15, 30] или 'off' — «пешком за N минут» | как в проекте |
pinShape | 'pin' — значок с точкой, 'badge' — значок, 'dot' — метка | как в проекте |
pinRadius | 0–50 — скругление пинов, %: 0 — квадрат, 50 — круг | как в проекте |
pinSize | 's', 'm', 'l' — размер пинов | как в проекте |
uiRadius | 0–24 — скругление кнопок, карточек и панелей, px; 24 — капсулы | как в проекте |
dockSize | 'm' — стандартный, 's' — маленький, 'xs' — очень маленький док | как в проекте |
timeOpen | true — время суток открыто сразу (лента часов над доком), false — по нажатию на «☀» | как в проекте |
height | px или 'auto' | 560 |
houses | цены, квартиры и строки карточек корпусов (ниже) | — |
controls | что из наших кнопок показывать (ниже) | все |
lazy | true — грузить, когда блок долистают | сразу |
view | 'house' — страница квартиры: ЖК с подсвеченным домом и кнопкой «Открыть карту» (ниже) | полная карта |
house | дом квартиры для view: 'house' — ID, название или подпись, как в selectHouse | — |
section | секция или подъезд дома для view: 'house', если дом из частей | весь дом |
openLabel | подпись кнопки «Открыть карту»; false — без кнопки | 'Открыть карту' |
Элементы управления
Спрячьте наши кнопки, если ставите свои. Переключайте — карта рядом меняется, а ниже — код, который получится.
Kinjo.mount('#kinjo-map', {
project: 'dom-na-yamskoy',
});Без JavaScript — атрибут data-controls="none" или "-time,-header"; у iframe — &ui=none.
Вид под стиль сайта
Форма и размер пинов мест, скругление элементов карты — дока, кнопок, карточек, плашек, панелей и листа на телефоне — и размер дока. Обычно это настраивают в кабинете: «Настройки проекта» → «Карта на сайте» → «Вид элементов». Параметры встраивания переопределяют проект для одного сайта.
Kinjo.mount('#kinjo-map', {
project: 'dom-na-yamskoy',
pinShape: 'badge', // значок без точки ('pin' — с точкой, 'dot' — метка)
pinRadius: 0, // квадратные пины (50 — круглые)
pinSize: 'm', // 's', 'm', 'l'
uiRadius: 0, // прямые углы у кнопок, карточек и панелей (24 — капсулы)
dockSize: 's', // док поменьше: 'm' — стандартный, 'xs' — очень маленький
});<div data-kinjo data-project="dom-na-yamskoy" data-pin-shape="badge" data-pin-radius="0" data-ui-radius="0"></div>У iframe — &pinShape=badge&pinRadius=0&pinSize=m&uiRadius=0&dockSize=s. Цвета пинов — по категориям из проекта. Смена параметров через Kinjo.update(el, {'{'} uiRadius: 12 {'}'}) перезагружает карту.
Методы
Все методы возвращают Promise. Команды, отправленные до загрузки карты, ждут её. Ошибка — Error с полем code: unknown_house, bad_args, unavailable, route_failed, origin_not_allowed, timeout.
selectHouse(ref)
Выбрать дом по ID, названию или подписи: откроется карточка, камера подлетит. Ответ — сведения о доме, вместе с продажами.
const house = await map.selectHouse('Корпус 1');
console.log(house.sales?.priceText); // «от 5,2 млн ₽»setHouses(houses) · updateHouse(ref, house)
Данные корпусов со страницы на лету: setHouses — заменить всё, updateHouse — один корпус поверх прежнего (null — убрать). Например, сайт подтянул цены из своей CRM уже в браузере.
await map.setHouses({ 'Корпус 2': { priceFrom: 7850000, flatsOnSale: 4 } });
await map.updateHouse('Корпус 2', { note: 'Последние 4 квартиры' });
await map.updateHouse('Корпус 2', null);setTime(time) · setDate(date)
«13:00» — время суток, Date — день и время по часовому поясу ЖК. Солнце и тени видны в 3D.
await map.setTime('22:30'); // ночь: окна светятся
await map.setDate('2026-12-21'); // зима
await map.setTime(new Date()); // сейчасsetMode(mode) · setTheme(theme)
Плоская карта или 3D; тема карты. Камера и выбранный дом сохраняются.
await map.setMode('2d');
await map.setTheme('dark');routeTo(to, { mode })
Маршрут от ЖК до адреса (первая подсказка поиска по городу ЖК) или до точки. Ответ — минуты и километры.
const r = await map.routeTo({ address: 'Тюмень, ул. Республики, 1' });
console.log(r.minutes, r.km, r.mode); // 23 1.7 'walk'
await map.routeTo({ lngLat: [65.534, 57.153], label: 'Офис продаж' }, { mode: 'drive' });
await map.clearRoute();showCategories(list) · showAllPlaces()
Только эти категории мест: edu — школы и сады, shops — магазины, health — здоровье, transport — транспорт, leisure — спорт и отдых.
await map.showCategories(['edu', 'health']);
await map.showAllPlaces();setWalkZone(minutes) · openCity()
Зона «пешком за N минут» (какие есть — в ready.walkZones) и «Город» — сколько ехать до аэропорта, вокзала, центра.
await map.setWalkZone(15);
await map.setWalkZone(null);
await map.openCity();flyTo(camera) · resetView()
Камера: центр [lng, lat], масштаб, поворот, наклон, длительность в мс. resetView — начальный вид проекта.
await map.flyTo({ center: [65.5059, 57.1645], zoom: 18, bearing: 60, pitch: 62 });
await map.resetView();setControls('none')
Спрятать наши кнопки и поставить свои — или вернуть. При встраивании то же самое — параметр controls.
await map.setControls('none'); // только карта
await map.setControls({ time: true }); // вернуть время
await map.setControls('all');Ещё: getState() — режим, выбранный дом, время; destroy() — убрать карту.
События
Подписка — map.on(name, fn), map.off, map.once. Те же события приходят на блок карты как kinjo:<name>. Нажмите что-нибудь на карте — события появятся здесь.
- Пока тихо: выберите корпус на карте или нажмите «Выполнить» у метода.
| Событие | Когда и что приходит |
|---|---|
ready | карта загрузилась: дома, категории, зоны «пешком», есть ли «Город» и маршрут |
houseSelect | выбрали дом (на карте или командой); null — выбор сняли. Вместе с продажами |
placeSelect | открыли место рядом: название, категория, «≈ 7 мин пешком»; у места прямо в ЖК — inComplex: true и без времени |
routeBuilt | построили маршрут: куда, пешком или на машине, минуты, километры |
routeClear | маршрут убрали |
timeChange | время на карте (3D), не чаще 4 раз в секунду |
modeChange | переключили 2D / 3D |
flatsClick | нажали «Смотреть квартиры» в карточке корпуса |
mapOpen | страница квартиры (view: 'house'): нажали «Открыть карту» |
mapClose | страница квартиры: полную карту закрыли |
error | проект не найден, сайт не в списке, карта не отвечает |
map.on('ready', (info) => console.log(info.houses));
map.on('houseSelect', (house) => {
if (!house) return; // выбор сняли
showMyCard(house.name, house.sales?.priceText, house.url);
});
map.on('routeBuilt', (r) => console.log(r.to, r.minutes, r.mode));
map.on('flatsClick', (h) => ym(XXXXXX, 'reachGoal', 'kinjo_flats'));Свой iframe
Если на сайте уже стоит iframe с картой, подключитесь к нему — тот же объект карты. Наши кнопки у iframe задаёт параметр ui: none — только карта, -time,-header — без перечисленных.
<iframe id="kinjo-map" src="https://map.kinjo.ru/?project=dom-na-yamskoy&embed=1&ui=none"
style="width:100%;height:600px;border:0" allow="fullscreen"></iframe>
<script src="https://map.kinjo.ru/widget.js"></script>
<script>
const map = Kinjo.connect('#kinjo-map');
map.ready.then(() => map.selectHouse('Корпус 1'));
</script>Ограничение по сайтам
Кабинет → «Настройки проекта» → «Сайт и API» → «Сайты, где можно управлять картой». Если список задан, команды с других сайтов отклоняются (origin_not_allowed) и события туда не идут. Пусто — с любого. https://www.site.ru и https://site.ru — разные сайты.
Через API доступны только действия с картой: никаких данных кабинета, черновиков и ключей. Карта принимает команды только от страницы, в которую встроена, и отвечает только ей.
Типы TypeScript
Методы, параметры и события описаны в kinjo.d.ts: положите файл в проект — window.Kinjo станет типизированным.
// скачайте https://map.kinjo.ru/kinjo.d.ts в проект (например, types/kinjo.d.ts)
import type { KinjoMap, KinjoHouse } from './types/kinjo';
const map: KinjoMap = Kinjo.mount('#kinjo-map', { project: 'dom-na-yamskoy' });
map.on('houseSelect', (house: KinjoHouse | null) => { /* … */ });useEffect(() => {
const map = window.Kinjo.mount(ref.current, { project: 'dom-na-yamskoy' });
map.on('houseSelect', setHouse);
return () => map.destroy();
}, []);Для CRM и без разработчика (необязательно)
Если сайт не передаёт цены сам, их можно задать у нас — тогда они видны везде, где стоит карта, и тоже без публикации.

В кабинете
Редактор модели → клик по корпусу → «Продажи (по желанию)»: ссылка, цена, число квартир, предпросмотр карточки. Там же ID дома для API с кнопкой копирования.
HTTP API для CRM
Ключ: кабинет → «Настройки проекта» → «Сайт и API» → «Расширенно: ключи API для CRM» → «Создать ключ». Ключ показывается один раз, у нас хранится только его хэш. Держите его на сервере, не в коде страницы.
curl -X PUT https://api.kinjo.ru/api/v1/projects/vash-zhk/houses/k1/sales \
-H "Authorization: Bearer kj_live_…" \
-H "Content-Type: application/json" \
-d '{"priceFrom": 5200000, "flatsOnSale": 12, "url": "https://ваш-сайт.ru/flats?korpus=1"}'Поля необязательные: priceFrom — ₽, целое; flatsOnSale — целое; url — только https://. PUT заменяет продажи корпуса целиком, пустое тело {} их убирает. houseId — ID дома из кабинета (ID части дома тоже подходит).
{
"house": { "id": "k1", "name": "Корпус 1" },
"sales": { "url": "https://ваш-сайт.ru/flats?korpus=1", "priceFrom": 5200000, "flatsOnSale": 12,
"updatedAt": "2026-10-19T09:00:00.000Z" },
"live": true
}# убрать продажи корпуса
curl -X DELETE https://api.kinjo.ru/api/v1/projects/vash-zhk/houses/k1/sales -H "Authorization: Bearer kj_live_…"
# ID домов, названия и текущие продажи
curl https://api.kinjo.ru/api/v1/projects/vash-zhk/houses -H "Authorization: Bearer kj_live_…"| Код | Когда |
|---|---|
200 | сохранено; в ответе — дом и продажи |
400 | не JSON или поле не прошло проверку, в issues — что не так |
401 | нет ключа, ключ неверный или отозван |
403 | ключ от другого проекта |
404 | нет такого проекта или дома |
413 | тело больше 8 КБ |
429 | больше 120 запросов в минуту с ключом или много неверных ключей с одного адреса; Retry-After — через сколько секунд |
Ошибки — JSON { "message": "…" } по-русски. Лимит — 120 запросов в минуту на ключ. Данные со страницы сайта (JSON выше) главнее этих.