| Method | Endpoint | Назначение |
|---|---|---|
| GET | /health | Проверить ключ и соединение |
| GET | /schema | Получить актуальный machine-readable контракт полей |
| POST | /leads | Передать один лид или batch |
| GET | /stats | Статистика интеграции |
| GET | /leads/:externalId?source=ss.ge | Проверить статус конкретного лида |
Поддерживаются 4 формы запроса: один объект, {lead:{...}}, {leads:[...]} или JSON-массив.
POST https://m2m.eco/api/partner-ingest/v1/leads
Authorization: Bearer <API_KEY>
Content-Type: application/json
Idempotency-Key: unique-delivery-id
{
"leads": [
{
"external_id": "36854194",
"source": "ss.ge",
"source_listing_id": "36854194",
"property_group_id": "20609",
"source_url": "https://home.ss.ge/ru/real-estate/36854194",
"seller_type": "собственник",
"seller_confidence_pct": 70,
"seller_confidence_reason": "отметка площадки: physical",
"property_type": "квартира",
"property_price_usd": 130000,
"price": 130000,
"currency": "USD",
"property_area_m2": 83,
"rooms": 4,
"bedrooms": 3,
"floor": "2/8",
"condition": "старый ремонт",
"city": "Батуми",
"district": "Багратиони",
"address": "М. Комахидзе 97",
"cadastral_number": "05.31.01.551",
"contact_phone": "+995558239392",
"masked_phone": "558239***",
"contact_name": "Alex",
"source_seller_type": "physical",
"seller_listings_count": 2,
"phone_listings_count": 1,
"photos": ["https://static.ss.ge/1.jpg"],
"photo_count": 1,
"published_at": "2026-09-30T10:06:00+04:00",
"found_at": "2026-09-30T10:14:00+04:00",
"title": "Продается 4-комнатная квартира",
"description": "Полное описание объявления",
"duplicate_urls": ["https://www.myhome.ge/ru/pr/26164619"],
"custom_fields": {
"balcony_type": "open",
"parser_score": 0.93
}
}
]
}
Для каждого лида нужен стабильный идентификатор: лучше external_id. Если его нет, API использует source_listing_id, затем property_group_id. Также нужен хотя бы один из title, description, source_url.
| Field | Type | Meaning |
|---|---|---|
external_id | string | Стабильный ID объявления/лида |
source | string | ss.ge, myhome.ge, korter.ge и т.д. |
source_listing_id | string | ID объявления на площадке |
source_url | string | Ссылка на исходное объявление |
property_group_id | string | ID одного объекта, если он найден на нескольких площадках |
duplicate_urls | string[] | Ссылки на этот же объект на других площадках |
seller_type | string | собственник / агент / другое |
seller_confidence_pct | number | Уверенность классификации 0–100 |
seller_confidence_reason | string | Почему сделан такой вывод |
title | string | Заголовок |
description | string | Полное описание |
property_type | string | квартира / дом / участок / коммерция |
transaction_type | string | sale / rent / другое |
property_price_usd | number | Цена, нормализованная в USD |
price | number | Цена в исходной валюте |
currency | string | USD / GEL / EUR |
property_area_m2 | number | Площадь объекта |
land_area_m2 | number | Площадь участка |
rooms | number | Комнаты |
bedrooms | number | Спальни |
floor | string | Например 2/8 |
condition | string | Состояние/ремонт |
residential_complex | string | ЖК |
city | string | Город |
district | string | Район |
address | string | Адрес |
map_url | string | Ссылка на карту |
cadastral_number | string | Кадастровый номер |
contact_phone | string | Основной телефон |
duplicate_phone | string | Телефон из дубля |
masked_phone | string | Телефон-маска |
contact_name | string | Имя продавца |
source_seller_type | string | Метка площадки: physical / Individual |
seller_listings_count | number | Объявлений у продавца |
phone_listings_count | number | Объявлений на телефоне |
contact_telegram | string | Telegram |
contact_whatsapp | string | |
photos | string[] | URL фотографий, максимум 40 |
photo_count | number | Количество фото |
published_at | string | Когда опубликовано |
found_at | string | Когда найдено парсером |
metadata | object | Служебные данные парсера |
custom_fields | object | Любые дополнительные поля |
Можно отправлять даже текущие русские названия колонок. API сам сопоставит их с канонической схемой.
| Excel | API |
|---|---|
| Тип продавца | seller_type |
| Уверенность | seller_confidence_pct |
| Почему | seller_confidence_reason |
| ID квартиры | property_group_id |
| Площадка | source |
| ID | source_listing_id |
| Ссылка | source_url |
| Эта же квартира на других площадках | duplicate_urls |
| Тип | property_type |
| Цена, $ | property_price_usd |
| Цена | price |
| Валюта | currency |
| Площадь, м² | property_area_m2 |
| Участок, м² | land_area_m2 |
| Комнат | rooms |
| Спален | bedrooms |
| Этаж | floor |
| Состояние | condition |
| ЖК | residential_complex |
| Город | city |
| Район | district |
| Адрес | address |
| Карта | map_url |
| Кадастр | cadastral_number |
| Телефон | contact_phone |
| Телефон из дубля | duplicate_phone |
| Телефон (маска) | masked_phone |
| Продавец | contact_name |
| Отметка площадки | source_seller_type |
| Объявлений у продавца | seller_listings_count |
| Объявлений на телефоне | phone_listings_count |
| Фото (все ссылки) | photos |
| Фото, шт | photo_count |
| Опубликовано | published_at |
| Найдено | found_at |
| Заголовок | title |
| Описание | description |
Если у партнёра появится новая колонка, интеграцию не нужно останавливать. Новые значения можно сразу отправлять в custom_fields. Неизвестные top-level ключи тоже сохраняются автоматически.
{
"external_id": "36854194",
"source": "ss.ge",
"source_url": "https://home.ss.ge/...",
"custom_fields": {
"balcony_type": "open",
"view_direction": "sea",
"owner_detection_model": "v3",
"owner_detection_features": ["physical", "single_phone"],
"parser_score": 0.94
}
}
Оригинальный входящий JSON хранится целиком. Максимум: 64 KiB на один lead, до 40 URL фото, до 100 leads в batch.
const baseUrl = 'https://m2m.eco/api/partner-ingest/v1'
const apiKey = process.env.MIGI_PARTNER_API_KEY
async function sendLeads(leads, deliveryId) {
const response = await fetch(`${baseUrl}/leads`, {
method: 'POST',
headers: {
'content-type': 'application/json',
'authorization': `Bearer ${apiKey}`,
'idempotency-key': deliveryId,
},
body: JSON.stringify({ leads }),
})
const body = await response.json()
if (!response.ok) throw new Error(`${response.status}: ${body.code || body.error}`)
return body
}
import os, requests, uuid
BASE = "https://m2m.eco/api/partner-ingest/v1"
API_KEY = os.environ["MIGI_PARTNER_API_KEY"]
payload = {"leads": [{
"external_id": "36854194",
"source": "ss.ge",
"source_url": "https://home.ss.ge/ru/real-estate/36854194",
"title": "Продается квартира",
"city": "Батуми"
}]}
r = requests.post(
BASE + "/leads",
json=payload,
headers={
"Authorization": f"Bearer {API_KEY}",
"Idempotency-Key": str(uuid.uuid4())
},
timeout=30,
)
r.raise_for_status()
print(r.json())
Принятый lead создаётся со статусом imported. Дальше MIGI проводит модерацию и может перевести его в review, on_sale, sold или rejected.
{
"ok": true,
"apiVersion": "v1",
"batchId": "...",
"accepted": 1,
"duplicates": 0,
"rejected": 0,
"total": 1,
"items": [{
"externalId": "36854194",
"source": "ss.ge",
"accepted": true,
"duplicate": false,
"partnerLeadId": "...",
"status": "imported",
"qualityScore": 100,
"warnings": []
}]
}
Batch может быть принят частично. Некорректные элементы возвращаются с rejected:true, code и error, а корректные элементы из того же batch сохраняются.
| Code | Meaning |
|---|---|
API_KEY_INVALID | Ключ отсутствует, неверный или отозван |
LEADS_REQUIRED | Нет лидов в запросе |
BATCH_TOO_LARGE | Больше 100 лидов |
IDEMPOTENCY_CONFLICT | Один Idempotency-Key использован для разных payload |
EXTERNAL_ID_REQUIRED | Нет external/source listing/property group ID |
LEAD_CONTENT_REQUIRED | Нет title, description и source_url |
SOURCE_NOT_ALLOWED | Этот API key не разрешён для такой площадки |
LEAD_TOO_LARGE | Один JSON lead больше 64 KiB |
RATE_LIMITED | Слишком много запросов |
Используйте batch по 20–50 лидов, хотя hard limit — 100. Для каждой отправки создавайте уникальный Idempotency-Key. Один и тот же объект повторно не создаст новый lead: dedup работает в рамках партнёра по source + external_id.
GET /health.GET /schema.POST /leads.accepted: 1.GET /leads/:externalId?source=....