Skip to main content
Seeki.eu

Agency Import API

Надсилайте оголошення до Seeki через API.

Масовий імпорт оголошень нерухомості з CRM або системи управління нерухомістю. Один endpoint, статус кожного елемента, автоматичний TTL.

Отримати API-ключ

Доступ до Agency Import API вимагає активної підписки агенції Seeki. Кожна підписка постачається з одним API-ключем, прив'язаним до вашого облікового запису агенції.

Оформіть підписку на сторінці для агентів для початку роботи.

UI для управління ключами (перегляд, ротація, відкликання) з'явиться в майбутньому оновленні панелі. Наразі API-ключ надсилається на пошту при активації підписки. Зверніться до info@seeki.eu, якщо вам потрібен новий ключ.

Автентифікація

Кожен запит повинен містити API-ключ як Bearer-токен в заголовку Authorization.

HTTP header
Authorization: Bearer seeki_live_your_key_here

Ключі, що починаються з seeki_live_, є продакшн-ключами. Ключі стейджингу починаються з seeki_test_. Вони не взаємозамінні між середовищами.

Перший імпорт

Надішліть POST-запит на /v1/listings з JSON-тілом, що містить масив listings. Кожен елемент представляє один об'єкт нерухомості.

curl
curl -X POST https://ingest.seeki.eu/v1/listings \
  -H "Authorization: Bearer seeki_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "listings": [
      {
        "external_id": "crm-listing-00123",
        "listing_type": "SELL",
        "real_estate_type": "APARTMENT",
        "price": 320000,
        "currency": "EUR",
        "address": {
          "street": "Wenceslas Square 1",
          "city": "Prague",
          "country_code": "CZ",
          "postal_code": "11000"
        },
        "name": "Sunny 2-bedroom apartment, Wenceslas Square",
        "floorage": 65
      }
    ]
  }'

Успішний пакет повертає HTTP 200 з масивами accepted і rejected:

200 OK
{
  "accepted": [
    { "external_id": "crm-listing-00123", "import_item_id": "uuid-…" }
  ],
  "rejected": []
}

Структура запиту

Верхній рівень тіла це { listings: [...] }. Обов'язкові поля для кожного оголошення:

ПолеОбов'язково?Примітки
external_idОбов'язковоУнікальний ID вашої CRM. Використовується для ідемпотентних повторних імпортів і дедублікації.
listing_typeОбов'язковоSELL або RENT.
real_estate_typeОбов'язковоAPARTMENT, HOUSE, LAND, COMMERCIAL або OTHER.
priceОбов'язковоЧисловий. Використовуйте поле currency для коду ISO 4217 (за замовчуванням EUR).
address OR coordinatesОбов'язковоНадайте об'єкт адреси (street, city, country_code) або координати ({ lat, lng }). Принаймні одне має бути присутнє.
currencyНеобов'язковоКод ISO 4217, напр. EUR, CZK, PLN. За замовчуванням EUR.
name, descriptionНеобов'язковоЗаголовок оголошення та вільний опис.
floorage, floor, roomsНеобов'язковоПлоща нерухомості в м², номер поверху та кількість кімнат.
imagesНеобов'язковоМасив публічних URL зображень. Воркер імпорту завантажує та кешує їх.
contactНеобов'язковоІм'я агента, пошта та телефон для маршрутизації запитів.

Повна схема з усіма необов'язковими полями в інтерактивній API reference.

Структура відповіді та помилки

Endpoint /v1/listings завжди повертає HTTP 200 OK, поки сам запит є правильним (валідний JSON, правильний заголовок auth, в межах обмежень розміру). Збої окремих оголошень звітуються в масиві rejected, а не як коди HTTP-помилок.

Кожен відхилений елемент містить external_id, error_code та читабельне повідомлення. Помилки рівня пакету (погана автентифікація, занадто великий payload) повертають не-200 HTTP статус з верхньорівневим error_code.

Коди помилок

Коди рівня пакету повертають HTTP-помилки. Коди рівня елемента з'являються в масиві rejected відповіді 200.

error_codeHTTP / областьЗначення
MISSING_AUTHORIZATION401Не надіслано заголовок Authorization.
INVALID_KEY401Ключ не знайдено, відкликано або прострочено.
SUBSCRIPTION_INACTIVE403Підписка агенції не активна або прострочена.
PAYLOAD_TOO_LARGE413Тіло запиту перевищує ліміт 25 МБ.
TOO_MANY_ITEMS413Масив listings містить більше 5 000 елементів.
VALIDATION_FAILEDелементОдне або кілька обов'язкових полів відсутні або мають недійсне значення. Перевірте поле message для деталей.
GEOCODE_ADDRESS_NOT_FOUNDелементНадану адресу не вдалося перетворити на координати. Перевірте street, city та country_code.
GEOCODE_COORDINATES_INVALIDелементНадані lat/lng виходять за допустимі діапазони (lat ±90, lng ±180).
INFRA_QUEUE_REJECTEDелементЧерга workflow відхилила елемент, зазвичай через тимчасове перевантаження. Повторіть після короткої затримки.
INFRA_LOSTелементWorkflow було прийнято, але його результат ніколи не записано. Використовуйте endpoint повторної спроби.
INTERNAL_ERRORелементСталася несподівана помилка сервера. Повторна спроба може вдатися; зверніться до підтримки, якщо проблема не зникає.

Ідемпотентність / повторні імпорти

Повторне надсилання оголошення з тим самим external_id оновлює наявний запис, а не створює дублікат. TTL оголошення оновлюється при кожному успішному імпорті.

Внутрішньо кожен елемент імпорту відповідає Cloudflare Workflow з ID:

Workflow ID pattern
agency-{agency_id}-{external_id}

Закінчення терміну дії оголошення

Кожне імпортоване оголошення має TTL 60 днів з моменту останнього успішного імпорту. Після закінчення TTL оголошення автоматично знімається з публікації щоденним cron-завданням.

Щоб підтримувати оголошення активним безстроково, повторно імпортуйте його (навіть з ідентичними даними) до закінчення 60-денного вікна. Рекомендований патерн це нічна ресинхронізація активних оголошень.

Статус + повторна спроба

Використовуйте GET /v1/import-items/{import_item_id}/status для опитування стану обробки одного елемента. import_item_id повертається в масиві accepted початкового POST-відповіді.

GET /import-items/{id}/status
curl https://ingest.seeki.eu/v1/import-items/{import_item_id}/status \
  -H "Authorization: Bearer seeki_live_your_key_here"
Response
{
  "import_item_id": "uuid-…",
  "external_id": "crm-listing-00123",
  "status": "completed",
  "listing_id": "uuid-listing"
}

Якщо елемент опинився в стані INFRA_LOST або INFRA_QUEUE_REJECTED, поставте його знову до черги без повторного надсилання повного пакету:

POST /import-items/{id}/retry
curl -X POST https://ingest.seeki.eu/v1/import-items/{import_item_id}/retry \
  -H "Authorization: Bearer seeki_live_your_key_here"

Обмеження

  • Розмір тіла: максимум 25 МБ на запит.
  • Елементів на запит: максимум 5 000. Розбийте більші пакети.
  • Обмеження QPS наразі не застосовується. Дуже великі сплески можуть автоматично обмежуватися; розподіляйте синхронізації великих обсягів між кількома запитами.

OpenImmo XML / zip intake

OpenImmo is the de-facto real-estate exchange format for the DACH market (Germany, Austria, Switzerland) and is produced by every major CRM in those countries — FlowFact, onOffice, ImmoMaster, edomi, and others. If your CRM already exports OpenImmo, you can POST it directly without remapping fields into Seeki-JSON.

Two delivery flavours are accepted on the same endpoint, distinguished byContent-Type:

  • application/xml — raw OpenImmo XML, images referenced by absolute URL.
  • application/zip — bundle containing index.xml at the root plus the JPGs referenced from <anhang gruppe="INTERN"> nodes. We extract every referenced image, host it on Supabase Storage, and rewrite the listing’s media.images array before publication. Hosted images are removed when the listing expires (60-day default TTL); re-imports refresh them.
curl — XML
curl -X POST https://ingest.seeki.eu/v1/openimmo \
  -H "Authorization: Bearer seeki_live_your_key_here" \
  -H "Content-Type: application/xml" \
  --data-binary @export.xml
curl — zip
curl -X POST https://ingest.seeki.eu/v1/openimmo \
  -H "Authorization: Bearer seeki_live_your_key_here" \
  -H "Content-Type: application/zip" \
  --data-binary @export.zip

Target spec version: OpenImmo 1.2.x. Body cap: 200 MB. Bigger feeds get a 413 with a Suggested-Chunk-Size: 500 header — split index.xml into multiple POSTs of ≤500 listings each. Spec reference: openimmo.de.

The same per-item error codes from the JSON intake apply — only the request body format differs. Each <immobilie> that fails Zod validation appears in the response’s rejected array with a VALIDATION_FAILED code and the offending field path.

Idealista XML-ML intake

Idealista’s XML-ML (xmlGenerator) is the standard feed format on the Iberian peninsula — used by Idealista itself and the CRMs that export to it for the Spanish (ES) and Portuguese (PT) markets. Country is inferred per record from the <provincia> field; locale follows country.

Images are referenced by URL (<imagenes><imagen url="…"/>), so there is no zip flavour for this format — application/xml only. Listings without an accessible image URL are still accepted; only fields that fail Zod validation are rejected.

curl
curl -X POST https://ingest.seeki.eu/v1/idealista \
  -H "Authorization: Bearer seeki_live_your_key_here" \
  -H "Content-Type: application/xml" \
  --data-binary @feed.xml

Target spec: Idealista xmlGenerator-1.X. The XML prolog encoding declaration is honoured — feeds shipped as windows-1252 are decoded correctly without manual conversion. Body cap: 200 MB. Spec reference: search Idealista’s help centre for “XML feed schema”.

Same per-item error codes as the JSON intake — see the table above.

Запуск

Існує два окремі середовища. API-ключі прив'язані до середовища: продакшн-ключ не працює на стейджингу, і навпаки.

СередовищеБазовий URL
Стейджингhttps://ingest.seeki.store/v1
Продакшнhttps://ingest.seeki.eu/v1

Всі endpoints (/listings, /import-items/{id}/status, /import-items/{id}/retry) ідентичні в обох середовищах.

Готові до інтеграції?

Відкрийте інтерактивну reference для вивчення всіх полів, тестування запитів у браузері та завантаження JSON Schema для вашого валідатора.