Как подключить внешнюю систему к API
Эта инструкция — для технического специалиста (программиста 1С, разработчика CRM или другой учётной системы), которому нужно подключить свою систему к API Базис Недвижимость: обмениваться сделками, объектами недвижимости, приёмками и другими данными напрямую, без ручной выгрузки файлов.
Всё, что описано ниже, — реальные методы API. Полный и всегда актуальный список методов и параметров смотрите в Swagger-документации: https://iflat.io/api/documentation (см. ниже раздел 7 — как ей пользоваться).
1. Авторизация
1.1. Включите интеграцию и получите client_id / client_secret
Откройте Настройки → Интеграции → Своя интеграция.
Включите переключатель интеграции и сохраните.
Система сформирует и покажет на этой же странице client_id и client_secret — это идентификатор и секрет именно вашего приложения-интеграции (не пользователя).
Храните
client_secretв надёжном месте сразу после получения. Отдельного способа перевыпустить только секрет, не пересоздавая интеграцию заново, не предусмотрено.
1.2. Получите access-токен (вход по логину и паролю)
ПРИМЕР. Вам необходимо взять реальные данные со страницы "Своя интеграция" в настройках.
POST https://iflat.io/api/v1/oauth/token
Content-Type: application/json{
"username": "79261234567",
"password": "пароль_пользователя",
"account_id": 132,
"client_id": 324,
"client_secret": "wiOJc8yxgiSX",
"grant_type": "login"
}Ответ:
{
"token_type": "Bearer",
"access_token": "eyJ0eXAiOiJKV1Qi...",
"expires_in": 86400,
"refresh_token": "def5020007002f25..."
}Дальше в каждом запросе к API передавайте заголовок:
Authorization: Bearer eyJ0eXAiOiJKV1Qi...Access-токен живёт 1 сутки (86400 секунд). После истечения запросы с ним будут отклонены с кодом 401 — нужно обновить токен.
1.3. Обновите токен, когда он истекает
POST https://iflat.io/api/v1/oauth/token{
"refresh_token": "def5020007002f25...",
"client_id": 324,
"client_secret": "wiOJc8yxgiSX",
"grant_type": "refresh_token"
}В ответ придёт новая пара access_token / refresh_token — без повторного ввода логина и пароля. Refresh-токен действует 30 дней с момента последнего использования. Если он тоже истёк — нужна повторная авторизация по логину и паролю (шаг 1.2).
Отдельного тестового стенда (песочницы) со своим адресом нет — настройка и проверка интеграции идут сразу на боевом аккаунте застройщика. Будьте аккуратны с тестовыми запросами на создание/изменение данных.
1.4. Ограничьте права интеграции отдельным пользователем и ролью
Важный момент: client_id/client_secret — это удостоверение вашего приложения, а вот какие данные оно увидит и что сможет изменить, определяется пользователем, чей телефон и пароль вы указали в username/password при получении токена. Интеграция получает ровно те права, что есть у этого пользователя (роль, права доступа, ограничения по подразделениям/объектам).
Не используйте для интеграции личный аккаунт администратора. Правильный подход:
Настройки → Роли → Создать — заведите отдельную роль, например «API-интеграция», и отметьте только те права, которые реально нужны интеграции (например, только «Объекты: просмотр и редактирование», без доступа к финансам, замечаниям и настройкам).
Настройки → Сотрудники → Добавить сотрудника — заведите отдельного пользователя (можно с техническим номером телефона) и назначьте ему созданную роль.
Используйте телефон и пароль именно этого пользователя в запросе получения токена (п. 1.2).
Это даёт:
Минимум прав — если интеграцию взломают, доступ ограничен ровно тем, что ей разрешили, а не всей системой.
Простой отзыв доступа — чтобы отключить интеграцию, достаточно удалить/деактивировать этого пользователя в Настройках, не трогая реальных сотрудников.
Разделение в истории изменений — все действия интеграции в системе фиксируются от имени этого технического пользователя, а не реального сотрудника.
2. embed — получить связанные данные одним запросом
По умолчанию GET-методы возвращают только собственные поля сущности (например, у Помещения — номер, площадь, статус_id и т.д.), но не разворачивают связанные объекты (сам Дом, сам Статус и т.д.) — это ускоряет ответ и уменьшает объём данных.
Чтобы получить связанные данные в том же запросе, передайте query-параметр embed — список названий связей через запятую. Вложенные связи указываются через точку.
GET /api/v1/rooms?embed=status,custom_fields
GET /api/v1/inspections?embed=room.house,room.dealПодключайте только то, что действительно нужно — чем больше
embed, тем больше объём ответа и медленнее запрос.
Список доступных для конкретной сущности связей отличается от метода к методу и всегда указан в описании параметра embed в Swagger для этого метода (раздел 7).
3. Внешние ID сущностей (Сделки, Приёмки, Квартиры)
Когда вы создаёте или обновляете запись через API (например, при импорте, раздел 6) и передаёте свой идентификатор записи во внешней системе, iFlat сохраняет карту соответствия: связку «запись iFlat ↔ ваш external_id» в разрезе источника данных (provider). Затем эту связку можно получить обратно.
Для собственной интеграции (не CRM вроде AmoCRM/Bitrix24) используйте provider = 6 («Своя интеграция»).
3.1. Получить карту соответствия по сущности (Room, House, District, Deal, User)
Специфичный метод для работы с картой отдельно. Используется в редких случаях.
GET /api/v1/externalObjects/{type}/maps?provider=6&internalIds[]=1726
GET /api/v1/externalObjects/{type}/maps?provider=6&externalIds[]=MY-EXT-001
{type} — один из: Room, House, District, User, Deal. Нужно передать либо externalIds[] (ваши ID), либо internalIds[] (ID в iFlat) — в зависимости от того, что известно.
Ответ:
{
"data": [
{
"id": 501,
"object_id": 1726,
"object_type": "Room",
"external_id": "MY-EXT-001",
"provider": 6,
}
]
}3.2. Получить внешний ID вместе с самой сущностью через embed
Room, House, District и Deal поддерживают связь provider_maps — её можно подключить через embed, не вызывая отдельный метод. Часто используемый вариант.
GET /api/v1/rooms?embed=provider_mapsКаждая запись в ответе будет содержать массив provider_maps с полями external_id и provider.
3.3. Пример: Приёмки с Квартирами и внешним ID одним запросом
Приёмка (Inspection) не хранит внешний ID сама по себе — он есть только у связанной с ней Квартиры (Room). Чтобы получить список изменённых приёмок вместе с внешним ID их помещений за один запрос:
GET /api/v1/inspections?embed=room.provider_maps&updatedAtFrom=2026-07-16T14:32:12Ответ (сокращённо):
{
"data": [
{
"id": 9012,
"status_id": 3,
"updated_at": "2026-07-16T15:02:44",
"room": {
"id": 1726,
"number": "42",
"provider_maps": [
{ "external_id": "MY-EXT-001", "provider": 6 }
]
}
}
]
}Если для помещения ещё не было создано соответствие — provider_maps придёт пустым массивом []. В этом случае либо сопоставьте запись по другому признаку (например, номеру помещения), либо создайте карту соответствия отдельным запросом POST /api/v1/externalObjects/Room/maps (тело: object_id, external_id, provider).
Важно! Параметр updatedAtFrom/updatedAtTo доступен для всех сущностей API и позволяет запрашивать только изменённые за период записи — не выгружайте каждый раз всю базу целиком.
3.4. Запись: привязать внешний ID к Квартире при создании/обновлении
Внешний ID можно передать не отдельным запросом, а прямо в теле создания или обновления сущности (Room, House, District, Deal, User) — массивом provider_maps:
PUT /api/v1/rooms/1726
{
"number": "42",
"provider_maps": [
{
"provider": 6,
"external_id": "MY-EXT-001"
}
]
}Такой же массив
provider_mapsможно передать и вPOST /api/v1/roomsпри создании новой квартиры — карта соответствия будет создана сразу вместе с записью.
Пустой
external_id(пустая строка) в элементе массива игнорируется — такая карта не сохранится и не обновится.При импорте через
POST /import(раздел 6) — карту передавать не нужно, так как там указываются вашиidна верхнем уровне записи и карта соответствия создается автоматически.
4. Фильтр по externalId — найти свою запись по своему ID
Если вы знаете только свой (внешний) идентификатор записи и хотите найти, что ей соответствует в iFlat, — есть два способа:
Способ 1 (с явным указанием источника). Тот же метод, что и в п. 3.1:
GET /api/v1/externalObjects/Room/maps?provider=6&externalIds[]=MY-EXT-001
В ответе — object_id (внутренний ID в iFlat) и, если передали withObject=true, вся запись целиком. Несмотря на то, что в данном методе можно получить и сам связанный объект, в нем нельзя получить связи, для этого лучше подойдет способ №2 ниже.
Способ 2 (короткий, только для Room/House/District/Work/Contract/WorkRegister). Некоторые списки сущностей принимают externalId прямо как фильтр в GET-списке (можно перечислить несколько через запятую):
GET /api/v1/rooms?externalId=MY-EXT-001,MY-EXT-002
Этот способ проще, но не позволяет уточнить, от какого именно провайдера искать ID — используйте его, только если уверены, что в аккаунт данные заводятся из одного внешнего источника.
5. Кастомные поля
Список кастомных (пользовательских) полей и их коды настраивает администратор застройщика в Настройки → Справочники → Пользовательские поля — уточните эти коды у администратора перед началом интеграции.
5.1. Чтение — embed=custom_fields
GET /api/v1/rooms/1726?embed=custom_fields{
"custom_fields": [
{ "code": "free_plan", "value": true },
{ "code": "ceiling_height", "value": 2.8 }
]
}
Это массив объектов, у каждого — код поля (code) и его значение (value).
5.2. Запись — объект code => value
При создании или обновлении записи кастомные поля передаются не массивом, а объектом, где ключ — это код поля, а значение — то, что нужно сохранить:
{
"number": "42",
"custom_fields": {
"free_plan": true,
"ceiling_height": 2.8
}
}Обратите внимание: формат чтения (массив объектов с
code/value) отличается от формата записи (плоский объекткод: значение). Это две разные формы одних и тех же данных — не путайте их местами.
6. Массовая загрузка — POST /import
Если нужно создать или обновить сразу много записей (сделки, объекты, работы), используйте один метод импорта вместо отдельного запроса на каждую запись.
Частая ошибка — отправлять каждую сделку или объект отдельным запросом в цикле. Это резко замедляет загрузку и создаёт лишнюю нагрузку на систему. Правильный способ — один запрос с массивом всех записей.
POST https://iflat.io/api/v1/import
{
"import_mode": "create_or_update",
"entity": "Room",
"system": "Basis",
"format": "Json",
"data_raw": [
{ "id": "MY-EXT-001", "number": "42", "house_id": 15, "...": "..." },
{ "id": "MY-EXT-002", "number": "43", "house_id": 15, "...": "..." }
],
"params": {
"provider_id": 6,
"custom_field_map": [
{ "source": "pb3f", "target": "free_plan" }
],
"status_map": [
{ "source": 1504, "target": 6 }
]
}
}Ответ:
{
"new": 2,
"updated": 3,
"skipped": 0,
"errors": [],
"read_errors": 0,
"validation_errors": 0,
"logic_errors": 0
}Что важно знать:
entity— какую сущность грузим:Room,DealилиWork.system— название формата системы. Если для вашей системы подходящего адаптера ещё нет — сначала согласуйте это с поддержкой, через API это не настраивается самостоятельно. Либо используйте стандартный формат "Basis"format— толькоJsonилиXml. Excel через API не поддерживается (пошаговое сопоставление колонок доступно только вручную в панели).Загрузка — синхронная: ответ приходит сразу по итогам обработки всего пакета, отдельной асинхронной очереди для больших объёмов нет. Ориентировочный предел — около 5000 записей в одном запросе (точнее зависит от объёма данных).
В записи должен быть передан
id(ваш собственный идентификатор) — поиск существующей записи для обновления идёт в первую очередь по нему (через карту соответствия, см. раздел 3).Права на импорт проверяются так же, как при обычном редактировании (например, для
Dealнужно правоСделки: редактирование, дляRoom—Объекты: редактирование) — убедитесь, что роль вашего технического пользователя (раздел 1.4) их включает.
7. Swagger — полная документация по методам
Полное описание всех методов API, их параметров и примеров запросов/ответов — в Swagger:
https://iflat.io/api/documentation
Если раньше не пользовались Swagger — это страница-справочник, всегда синхронизированная с реальным API. Коротко, как ей пользоваться:
Откройте ссылку — увидите список разделов (тегов): «Авторизация», «Помещения», «Сделки», «Приёмка», «Импорт» и т.д.
Кликните на нужный раздел, затем на конкретный метод (строка с адресом вроде
GET /rooms) — раскроется описание: параметры запроса, обязательность, примеры значений и структура ответа.Swagger UI открывается уже авторизованным под вашим текущим пользователем в панели — вручную вставлять токен через кнопку Authorize не нужно. Просто нажимайте Try it out → Execute на любом методе, и запрос уйдёт от имени того пользователя, под которым вы вошли в панель iFlat.
У каждого метода есть блок Example Value / Schema — точный список полей ответа и их типы, включая кастомные поля и embed-связи, описанные выше.
Так как Swagger UI использует вашего текущего пользователя панели, а не пользователя интеграции, права на действия в нём будут соответствовать вашей личной роли, а не роли технического пользователя из раздела 1.4. Это удобно для изучения методов, но не подменяет реальный вызов API с
client_id/client_secretвашего приложения.
Отдельной готовой Postman-коллекции нет — при желании работать в Postman можно импортировать в него спецификацию OpenAPI по ссылке, указанной на странице документации.
8. Коды ответов API
Все ошибки возвращаются в формате JSON с общими полями success, message, а для бизнес-ошибок ещё и code (код ошибки) и detail:
Код | Значение | Что делать |
|---|---|---|
200 | Успешно | — |
400 | Бизнес-ошибка или ошибка валидации: данные некорректны, не хватает обязательного поля, нарушено бизнес-правило | Проверьте тело запроса и сообщение |
401 | Не авторизован: токен не передан, истёк или недействителен | Обновите токен (раздел 1.3) или пройдите авторизацию заново (раздел 1.2) |
403 | Авторизованы, но у пользователя интеграции нет прав на это действие | Проверьте роль технического пользователя интеграции (раздел 1.4) — не хватает нужного права |
404 | Запись не найдена | Проверьте ID в запросе |
429 | Слишком много запросов подряд (ограничение частоты) | Подождите время, указанное в поле |
500 | Системная ошибка: непредвиденная ошибка на сервере или в корне некорректный формат данных, который не удалось даже провалидировать | Проверьте формат JSON/XML запроса; если ошибка повторяется на корректных данных — обратитесь в поддержку с деталями запроса (url и тело запроса, которое отправляете) |
Частые вопросы
Можно ли протестировать интеграцию на отдельном тестовом стенде?
Нет, отдельной песочницы со своим адресом не предусмотрено — настройка и проверка идут на вашем аккаунте. Будьте аккуратны с тестовыми запросами на запись данных.
Я потерял client_secret — можно перевыпустить только его?
Отдельного способа нет. Секрет нужно сохранить сразу при получении в разделе Настройки → Интеграции → Своя интеграция.
У меня в коде каждая сделка/объект уходит отдельным запросом в цикле — это нормально?
Нет, так делать не стоит — это медленно и создаёт лишнюю нагрузку на систему. Соберите все записи в один массив и отправьте одним запросом через POST /import (раздел 6). А при получении данных используйте embed-параметры, вместо отдельных get-запросов.
Как узнать коды кастомных полей аккаунта?
Их видно в ответе с embed=custom_fields (поле code), либо можно заранее уточнить у администратора — он видит их полный список в Настройки → Справочники → Пользовательские поля.
Хотим сделать получение данных по расписанию, как получить только то, что поменялось, а не все данные?
Используйте в GET-запросах параметр updatedAtFrom - он вернет только те сущности, которые изменились или были созданы с указанной метки времени, например:
GET /api/v1/inspections?updatedAtFrom=2026-07-16T14:32:12Никогда не используйте расписание без этого фильтра, так как с каждым днем данных будет становиться все больше и он будет выкачивать всю историю с каждым новым запуском.