<?xml version="1.0" encoding="UTF-8"?>
<objects>
<object external_id="sample-min-001">
<type_code>apartment</type_code>
<title>Двухкомнатная квартира, минимальный пример</title>
</object>
<object external_id="sample-full-001">
<type_code>apartment</type_code>
<title>3-комнатная квартира с ремонтом</title>
<description>Светлая квартира рядом с метро.</description>
<price>95000</price>
<currency>USD</currency>
<status_code>draft</status_code>
<visibility>agency</visibility>
<rooms>3</rooms>
<images>
<image>https://example.com/sample-listing-1.jpg</image>
</images>
</object>
</objects>1. Что такое XML-импорт
XML-импорт позволяет CRM-агентству массово создавать и обновлять объекты (объявления) из файла или HTTPS-фида.
Объекты создаются только в рамках текущего агентства (X-Agency-ID / tenant context). Изменить объекты другого агентства нельзя.
Для доступа нужно право objects.import. Наличие objects.update само по себе массовый импорт не открывает.
Политика v1: upsert only — отсутствие объекта в новом фиде не удаляет и не архивирует существующие записи.
2. Поддерживаемые форматы
HATA XML v1 — рекомендуемый формат для полного доступа к возможностям HATA (корень <objects>, элементы <object external_id>).
Поддерживаемый HATA профиль импорта Yandex Realty Language (yandex_yrl_hata_v1) — подмножество официального YRL, адаптированное под Узбекистан.
Это не полная совместимость с Яндекс.Недвижимостью: российские федеральные ограничения могут игнорироваться; HATA не гарантирует приём файла самим Яндексом.
Официальный namespace YRL: http://webmaster.yandex.ru/schemas/feed/realty/2010-06 (документация проверена 2026-07-30).
3. Профиль YRL
- Корень <realty-feed>, элементы <offer internal-id> → external_id.
- Минимум: продажа/аренда; квартира, комната, дом, участок, гараж.
- География через справочники HATA; новые города/районы из XML не создаются.
- Валюты: UZS, USD. Площадь: м²; сотки → м² (1 сотка = 100 м²) без двойного преобразования.
- Неизвестные безопасные теги YRL → warning, не пишутся в EAV.
- Пример: /samples/yandex-yrl-hata-example.xml.
4. XML-фиды по URL
- CRM: вкладка «XML-фиды» на /objects/xml-import.
- Расписание: manual | every_6_hours | daily.
- v1: только публичные HTTPS URL (Basic Auth без encryption key не хранится).
- Неизменный checksum → статус unchanged, без лишних update.
- Очередь: RabbitMQ consumer; scheduler: python -m app.object_xml_feed_scheduler.main.
5. Ограничения
- Максимальный размер файла по умолчанию: 5 МБ (OBJECT_XML_IMPORT_MAX_BYTES).
- Максимум объектов в файле: 500 (OBJECT_XML_IMPORT_MAX_ITEMS).
- Кодировка: только UTF-8.
- Расширение: .xml; MIME: application/xml или text/xml.
- Одновременно один apply-импорт на агентство; preview (validate) можно запускать параллельно.
- Актуальные числовые лимиты также отдаёт GET /api2_0/object/imports/config и блок limits_config в ответе validate.
3. Формат XML
Корень: <objects>. Элементы: <object external_id="…">. Namespaces и DTD не поддерживаются.
Если status/visibility не указаны, применяются безопасные значения draft и agency. Отсутствие поля не делает объект публичным.
Неизвестные обычные теги — ошибка. Неизвестные EAV-коды не создаются автоматически.
| Поле | Обязательное | Тип | Описание | Пример |
|---|---|---|---|---|
| external_id (атрибут) | да | string | Внешний ID в рамках агентства | agency-sku-123 |
| title | да | string | Название объекта | 2-комн., Чиланзар |
| type_id или type_code | да | int / string | Тип объекта из справочника | apartment |
| description | нет | string | Описание | … |
| price | нет | number | Цена | 95000 |
| currency | нет | string(3) | ISO-код валюты | USD |
| status_id / status_code | нет | int / string | По умолчанию draft | draft |
| visibility | нет | enum | private|agency|public; по умолчанию agency | agency |
| deal_type_id / deal_type_code | нет | int / string | Тип сделки | sale |
| city_id / area_id / street_id | нет | int | Локация | 1 |
| address / house | нет | string | Адрес | Чиланзар |
| latitude / longitude | нет | number | Координаты | 41.285 |
| rooms / floor / floors_total | нет | int | Скалярные характеристики | 3 |
| total_area / living_area / kitchen_area | нет | number | Площади | 78.5 |
| fields/field@code | нет | EAV | Только существующие коды полей | renovation |
| images/image | нет | https URL | До 30 на объект; SSRF-защита | https://… |
4. Пример XML
Ниже и в файле /samples/object-xml-import-example.xml — минимальный и расширенный объекты. type_code и EAV-коды должны существовать в вашей базе.
5. Создание и обновление
- Идентификация: (owning_agency_id, external_id).
- Новый external_id → создание; существующий своего агентства → обновление.
- Дубль external_id в одном XML → ошибка валидации.
- Отсутствие объекта в новом XML ничего не удаляет и не архивирует.
- Изменение external_id существующего объекта через XML не поддерживается.
- Повтор одинаковых данных → unchanged; слот повторно не расходуется.
- Обновление уже активного объекта слот не занимает.
6. Проверка перед импортом
- Выберите XML → «Проверить файл» (validate).
- Изучите preview: всего / новых / обновлений / ошибок / нужных и доступных слотов.
- Исправьте критические ошибки; при listing_limit_reached запуск блокируется целиком.
- «Запустить импорт» → status queued → polling detail до terminal status.
- Скачайте CSV-отчёт при необходимости.
7. Статусы импорта
| Статус | Значение | Действие |
|---|---|---|
| validated | Файл проверен, объекты не изменены | Можно запустить импорт, если can_apply |
| queued | Импорт поставлен в очередь | Дождитесь running |
| running | Идёт обработка | Polling detail |
| completed | Успешно без ошибок объектов | Смотрите отчёт |
| completed_with_errors | Часть объектов с ошибками | Скачайте отчёт, исправьте XML |
| failed | Критический сбой или все ошибки | Повторите после исправления |
8. Ошибки
Ошибки объектов смотрите в таблице UI, GET …/errors или CSV report. Номер элемента — xml_index, путь — xml_path.
После исправления загрузите файл снова через validate.
| Код | Причина | Что делать |
|---|---|---|
| xml_invalid | Повреждённый или неверный XML | Проверьте UTF-8, корень <objects>, теги |
| xml_unsafe | DTD/entities/опасная вложенность | Уберите DOCTYPE и entity |
| file_too_large | Файл больше лимита | Уменьшите файл (по умолчанию 5 МБ) |
| too_many_items | Больше 500 объектов | Разбейте файл |
| validation_failed | Ошибки в объектах | Смотрите таблицу ошибок / отчёт |
| duplicate_external_id | Повтор external_id в файле или конфликт | Сделайте ID уникальным в файле |
| listing_limit_reached | Не хватает слотов тарифа | Снизьте публичные объекты или повысьте тариф |
| object_not_owned | external_id чужого агентства | Используйте свои ID |
| import_already_running | Уже идёт apply | Дождитесь завершения |
| import_not_found | Нет такого импорта | Повторите validate |
| import_expired | Истёк TTL файла | Заново проверьте файл |
| import_not_validated | Неверный статус для apply | Сначала validate |
| checksum_mismatch | Файл изменился | Повторите validate |
| unknown_field | Неизвестный тег | Удалите поле или смотрите контракт |
| unknown_eav_field | Неизвестный EAV code | Используйте код из справочника |
| missing_required | Нет обязательного поля | Добавьте external_id, title, type |
| invalid_enum | Недопустимое значение | Проверьте visibility/status |
| type_not_found | Тип не найден | Укажите существующий type_code/type_id |
| status_not_found | Статус не найден | Укажите существующий status_code |
| image_forbidden | Запрещённый URL изображения | Только публичный https |
| image_fetch_failed | Не удалось скачать изображение | Проверьте URL; объект всё равно может быть сохранён |
| redis_unavailable | Сервис блокировок временно недоступен | Повторите позже |
| queue_unavailable | Очередь импорта временно недоступна | Повторите позже |
9. Права доступа
Permission: objects.import — для всех API импорта и раздела CRM /objects/xml-import.
По умолчанию выдаётся ролям agency_admin, admin, manager, supervisor, platform_admin.
Скрытие пункта меню на frontend не заменяет проверку на backend (403).
10. Тарифные лимиты
Лимит max_active_listings применяется только к продавцам доски (board sellers). Для типичных CRM-агентств preview показывает applies=false и «Без лимита».
Слот занимают живые public/опубликованные объекты. draft/archived/deleted и другие неактивные статусы слот не занимают.
Если slot_required > available — импорт не запускается частично; код listing_limit_reached.
11. Изображения и безопасность
- Только https; localhost, private/link-local/reserved IP запрещены.
- Редиректы перепроверяются; таймаут и лимит размера ответа действуют.
- Ошибка одного изображения не откатывает весь импорт — пишется warning/ошибка по объекту.
12. API
Все ручки требуют JWT, tenant context и objects.import. Prefix: /api2_0.
- POST /object/imports/xml/validate — multipart file → preview + import_id (status validated).
- POST /object/imports/xml — body {import_id} → {import_id, status: queued}; apply в фоне.
- GET /object/imports — история агентства.
- GET /object/imports/{id} — детальный статус и счётчики.
- GET /object/imports/{id}/errors — ошибки по объектам.
- GET /object/imports/{id}/report — CSV-отчёт.
- GET /object/imports/config — лимиты для UI.