К списку

Как подключить внешнюю систему к API

21.07.2026
#Интеграции #Загрузка данных

Эта инструкция — для технического специалиста (программиста 1С, разработчика CRM или другой учётной системы), которому нужно подключить свою систему к API Базис Недвижимость: обмениваться сделками, объектами недвижимости, приёмками и другими данными напрямую, без ручной выгрузки файлов.

Всё, что описано ниже, — реальные методы API. Полный и всегда актуальный список методов и параметров смотрите в Swagger-документации: https://iflat.io/api/documentation (см. ниже раздел 7 — как ей пользоваться).


1. Авторизация

1.1. Включите интеграцию и получите client_id / client_secret

  1. Откройте Настройки → Интеграции → Своя интеграция.

  2. Включите переключатель интеграции и сохраните.

  3. Система сформирует и покажет на этой же странице 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 при получении токена. Интеграция получает ровно те права, что есть у этого пользователя (роль, права доступа, ограничения по подразделениям/объектам).

Не используйте для интеграции личный аккаунт администратора. Правильный подход:

  1. Настройки → Роли → Создать — заведите отдельную роль, например «API-интеграция», и отметьте только те права, которые реально нужны интеграции (например, только «Объекты: просмотр и редактирование», без доступа к финансам, замечаниям и настройкам).

  2. Настройки → Сотрудники → Добавить сотрудника — заведите отдельного пользователя (можно с техническим номером телефона) и назначьте ему созданную роль.

  3. Используйте телефон и пароль именно этого пользователя в запросе получения токена (п. 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. Коротко, как ей пользоваться:

  1. Откройте ссылку — увидите список разделов (тегов): «Авторизация», «Помещения», «Сделки», «Приёмка», «Импорт» и т.д.

  2. Кликните на нужный раздел, затем на конкретный метод (строка с адресом вроде GET /rooms) — раскроется описание: параметры запроса, обязательность, примеры значений и структура ответа.

  3. Swagger UI открывается уже авторизованным под вашим текущим пользователем в панели — вручную вставлять токен через кнопку Authorize не нужно. Просто нажимайте Try it outExecute на любом методе, и запрос уйдёт от имени того пользователя, под которым вы вошли в панель iFlat.

  4. У каждого метода есть блок 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

Бизнес-ошибка или ошибка валидации: данные некорректны, не хватает обязательного поля, нарушено бизнес-правило

Проверьте тело запроса и сообщение message/detail в ответе — там указана конкретная причина

401

Не авторизован: токен не передан, истёк или недействителен

Обновите токен (раздел 1.3) или пройдите авторизацию заново (раздел 1.2)

403

Авторизованы, но у пользователя интеграции нет прав на это действие

Проверьте роль технического пользователя интеграции (раздел 1.4) — не хватает нужного права

404

Запись не найдена

Проверьте ID в запросе

429

Слишком много запросов подряд (ограничение частоты)

Подождите время, указанное в поле retry_after, и повторите запрос

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

Никогда не используйте расписание без этого фильтра, так как с каждым днем данных будет становиться все больше и он будет выкачивать всю историю с каждым новым запуском.

ПОХОЖИЕ СТАТЬИ
Онлайн-календарь приемки: Как избежать очередей из дольщиков и сдать 100 квартир за неделю
Установка кабинета покупателя на свой сайт
Отправка Webhooks по событиям
Фид помещений: описание формата Базис.Недвижимость