API віддає ті самі дані, що й сайт: лоти Prozorro.Продажі, їхні зміни й ваші збережені фільтри. Підходить, щоб підтягнути лоти у свою CRM, таблицю чи сайт. Лише читання, відповіді — JSON.

Ключ і перший запит

Ключ створюється в кабінеті, на вкладці API. Він показується один раз — скопіюйте його одразу. Ключ передається в заголовку:

curl -H "Authorization: Bearer prs_ваш_ключ" \
  "https://parser.randomstar.org/api/v1/lots?kind=land_lease&region=Полтавська&per_page=5"

Замість Authorization можна надіслати X-Api-Key: prs_…. У рядку адреси ключ не приймаємо: звідти він потрапляє в журнали й історію браузера. Ключ — як пароль: не публікуйте його у фронтенді сайту чи в репозиторії. Загубили — відкличте в кабінеті й створіть новий. Ключів може бути до п’яти — наприклад, окремо для CRM і для скрипта.

Ліміти

Ліміт — кількість запитів на добу для акаунта (спільний для всіх його ключів); обнуляється опівночі за Києвом. Довідники (/kinds, /regions, /statuses) не рахуються і працюють без ключа.

ТарифЗапитів на добу
Профі1 000
Бізнес20 000

У кожній відповіді — заголовки X-RateLimit-Limit (ліміт), X-RateLimit-Remaining (скільки залишилося) і X-RateLimit-Reset (коли обнулиться, Unix-час). Ліміт вичерпано — відповідь 429 із заголовком Retry-After (секунди до обнулення).

Методи

ЗапитЩо повертає
GET /api/v1/lotsПошук лотів за умовами, сторінками
GET /api/v1/lots/UA-…Один лот: усі поля, історія змін, інші аукціони того ж об’єкта
GET /api/v1/changesСтрічка змін (нові лоти, ціна, дати, статус, документи, результат) — для синхронізації
GET /api/v1/filtersВаші збережені фільтри
GET /api/v1/filters/id/lotsЛоти за вашим фільтром — ті самі, про які пише бот
GET /api/v1/meЧий ключ, тариф, ліміт і скільки використано сьогодні
ВебхукМи самі надсилаємо нові лоти й зміни на вашу адресу
GET /api/v1/kinds, /regions, /statusesДовідники кодів (без ключа)

Адреса — https://parser.randomstar.org/api/v1/…. Підписи (тип, статус, тариф) — українською; ?lang=en — англійською.

Пошук лотів: /lots

Умови ті самі, що в каталозі й фільтрах кабінету, тож API бачить рівно те, що ви бачите на сайті.

ПараметрЗначення
qСлова з назви чи населеного пункту; номер UA-… або кадастровий номер — точний пошук
kindТип аукціону — код із /kinds, наприклад land_lease
regionОбласть — як у /regions, наприклад Полтавська, м. Київ
min, maxСтартова ціна, ₴
dealdiscount — лише зі знижкою повторного аукціону, dutch — лише голландські (ціна знижується на торгах)
statusopen (типово — приймають або скоро прийматимуть заяви), all або коди з /statuses через кому
published_since, modified_sinceДата чи дата й час ISO 8601: 2026-10-01, 2026-10-01T09:00:00+03:00
sortnew (типово), modified, deadline (кінець прийому заяв), price_asc, price_desc
page, per_pageСторінка й розмір (до 100, типово 20)

Відповідь:

{
  "data": [
    {
      "id": "LRE001-UA-20261002-88807",
      "url": "https://parser.randomstar.org/auctions/lre001-ua-20261002-88807/",
      "source_url": "https://prozorro.sale/auction/LRE001-UA-20261002-88807/",
      "kind": "land_lease", "kind_name": "Оренда землі",
      "status": "active_tendering", "status_name": "Прийом заяв",
      "title": "Аукціон з укладення договору оренди земельної ділянки…",
      "region": "Полтавська", "locality": "Лохвицький район",
      "price": {"amount": 16000.0, "currency": "UAH", "period": null, "vat_included": false},
      "discount_percent": null, "area_ha": 2.7999, "area_m2": null,
      "cadastral": "5322685300:00:002:0190",
      "dates": {"published": "2026-10-02T16:12:00+03:00", "modified": "…",
                "tender_end": "2026-10-15T20:00:00+03:00", "auction_start": "2026-10-16T11:25:00+03:00"},
      "cancelled": false
    }
  ],
  "meta": {"page": 1, "per_page": 20, "total": 125, "pages": 7}
}

Картка лота: /lots/UA-…

Номер аукціону — у будь-якому регістрі. До полів зі списку додаються: title_uk, title_en, auction_type, item_type, cav, location (координати), guarantee (гарантійний внесок), min_step, normative_value (нормативна грошова оцінка землі), land_purpose, lease_duration (ISO 8601, P7Y), seller (назва й ЄДРПОУ — лише юрособи й органи влади), platform, dates.tender_start, attempt, previous_auction_id, documents_count, bids_count, result_amount, а також:

  • changes — останні 50 змін лота (найновіші першими);
  • same_object_auctions — інші аукціони того ж об’єкта (повторні, з нижчою ціною).

Стрічка змін: /changes

Для синхронізації своєї бази: забирайте зміни по порядку й запам’ятовуйте курсор.

ПараметрЗначення
since_idКурсор: зміни з id більшим за нього. Без нього — зміни за останню добу
limitДо 500, типово 100
eventsЧерез кому: new, status, price, dates, docs, cancelled, result
q, kind, region, min, max, dealЛише зміни лотів, що підходять під умови
{
  "data": [
    {"id": 812345, "event": "price", "old": "920000", "new": "736000", "at": "2026-10-04T09:12:00+03:00",
     "lot": {"id": "…", "kind": "dgf", "price": {"amount": 736000.0, …}, …}}
  ],
  "meta": {"next_since_id": 812345, "has_more": false}
}

Наступний запит — з since_id = next_since_id. Якщо has_more = true, запитуйте одразу ще раз; інакше — через кілька хвилин (ми оновлюємо дані кожні 5 хвилин).

Ваші фільтри: /filters

/filters — список фільтрів із кабінету: id, назва, умови, чи ввімкнений, куди надсилає. /filters/id/lots — лоти за фільтром; параметри status, sort, page тощо — як у /lots. Змінили фільтр у кабінеті — API одразу бачить нові умови.

Вебхуки

Замість того щоб опитувати /changes, можна дати нам адресу — і ми самі надсилатимемо події: нові лоти за вашими фільтрами й зміни «Моїх лотів» (ті самі, що приходять у Telegram). Адреса задається в кабінеті, на вкладці API; там же — секрет підпису, кнопка тестового запиту й стан останньої доставки. Вебхук один на акаунт, адреса — лише https:// і лише публічна.

Події збираються кожні 5 хвилин і приходять пачкою — POST із JSON:

POST /radar-webhook HTTP/1.1
Content-Type: application/json; charset=utf-8
X-Radar-Event: lots
X-Radar-Delivery: dlv_3f9a1c2b4d5e6f70
X-Radar-Timestamp: 1791100000
X-Radar-Signature: sha256=5c1e…

{
  "id": "dlv_3f9a1c2b4d5e6f70",
  "type": "lots",
  "created_at": "2026-10-04T10:05:00+03:00",
  "events": [
    {
      "type": "lot.new",
      "reason": "filter",
      "filter": {"id": 12, "name": "Оренда землі · Полтавська"},
      "change": {"id": 812345, "event": "new", "old": null, "new": null, "at": "2026-10-04T10:01:12+03:00"},
      "lot": {"id": "LRE001-UA-20261004-12345", "url": "…", "price": {"amount": 16000.0, …}, …}
    },
    {
      "type": "lot.changed",
      "reason": "watch",
      "filter": null,
      "change": {"id": 812350, "event": "price", "old": "920000", "new": "736000", "at": "…"},
      "lot": {…}
    }
  ]
}
  • type події: lot.new — новий лот за фільтром; lot.changed — зміна лота, за яким ви стежите (поле change.event: status, price, dates, docs, cancelled, result); lot.relisted — той самий об’єкт виставлено повторно, а ви стежили за попереднім аукціоном (reason: relist; новий лот сам додається у відстеження).
  • lot — у тому ж вигляді, що в /lots. Повну картку можна взяти через /lots/UA-….
  • Тестовий запит із кабінету — X-Radar-Event: ping і порожній events.
  • Одна подія може прийти двічі (наприклад, ваш сервер прийняв дані, але відповів із помилкою), тож зберігайте за change.id.

Відповідь і повтори

Відповідайте кодом 2xx упродовж 10 секунд — пачка вважається доставленою. Інакше повторимо через 1, 5, 30 хвилин, 2 і 6 годин, після чого пачку буде відкинуто. Події приходять по порядку: поки пачка не доставлена, наступні чекають. Після 20 невдач поспіль вебхук вимикається — причина в кабінеті, увімкнути знову — кнопкою «Зберегти й перевірити». Перенаправлень (301, 302) не виконуємо: вказуйте кінцеву адресу.

Перевірка підпису

Підпис — HMAC-SHA256 від рядка {X-Radar-Timestamp}.{тіло запиту} із секретом із кабінету. Перевіряйте його і не приймайте запити, старші за кілька хвилин.

// PHP
$body = file_get_contents('php://input');
$ts   = (int)($_SERVER['HTTP_X_RADAR_TIMESTAMP'] ?? 0);
$sig  = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, getenv('RADAR_WEBHOOK_SECRET'));
if (!hash_equals($sig, $_SERVER['HTTP_X_RADAR_SIGNATURE'] ?? '') || abs(time() - $ts) > 300) {
    http_response_code(401); exit;
}
$data = json_decode($body, true);
foreach ($data['events'] as $e) { /* $e['type'], $e['lot']['id'] … */ }
http_response_code(200);
# Python (Flask)
import hmac, hashlib, os, time
from flask import request, abort

@app.post("/radar-webhook")
def radar_webhook():
    body = request.get_data()
    ts = request.headers.get("X-Radar-Timestamp", "0")
    sig = "sha256=" + hmac.new(os.environ["RADAR_WEBHOOK_SECRET"].encode(),
                               ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(sig, request.headers.get("X-Radar-Signature", "")) \
            or abs(time.time() - int(ts)) > 300:
        abort(401)
    for e in request.get_json()["events"]:
        ...  # e["type"], e["lot"]["id"]
    return "", 200

Помилки

Помилка — відповідь із кодом HTTP і тілом {"error": {"code": "…", "message": "…"}}.

HTTPcodeЩо сталося
400bad_sort, bad_status, bad_dateНеправильний параметр
401no_key, bad_keyНемає ключа, ключ невідомий або відкликаний
403plan_no_apiНа тарифі немає API
404lot_not_found, filter_not_found, unknown_methodНемає такого лота, фільтра чи методу
405method_not_allowedAPI лише для читання — тільки GET
429daily_limitВичерпано добовий ліміт

Приклади

PHP

$ch = curl_init('https://parser.randomstar.org/api/v1/lots?kind=privatization&sort=deadline');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('RADAR_API_KEY')],
]);
$res = json_decode(curl_exec($ch), true);
foreach ($res['data'] as $lot) {
    echo $lot['id'], ' — ', $lot['price']['amount'], ' ₴ — ', $lot['url'], PHP_EOL;
}

Python

import os, requests

r = requests.get(
    "https://parser.randomstar.org/api/v1/lots",
    params={"kind": "land_lease", "region": "Полтавська", "max": 200000},
    headers={"Authorization": "Bearer " + os.environ["RADAR_API_KEY"]},
    timeout=30,
)
r.raise_for_status()
for lot in r.json()["data"]:
    print(lot["id"], lot["price"]["amount"], lot["dates"]["tender_end"])

Синхронізація змін (Python)

since = load_cursor()            # 0 при першому запуску
while True:
    r = requests.get("https://parser.randomstar.org/api/v1/changes",
                     params={"since_id": since, "limit": 500, "kind": "dgf"},
                     headers={"Authorization": "Bearer " + KEY}, timeout=30).json()
    for ch in r["data"]:
        save(ch)                 # ваша обробка
    since = r["meta"]["next_since_id"]
    save_cursor(since)
    if not r["meta"]["has_more"]:
        break

Умови використання

  • Дані — відкриті дані Prozorro.Продажі. Показуючи лоти своїм користувачам, давайте посилання на джерело — поле source_url.
  • Персональних даних фізичних осіб в API немає: ми прибираємо їх ще під час збору.
  • Правила використання й ліміти — у публічній оферті. Є питання чи потрібен інший ліміт — напишіть нам.

Не знайшли відповіді?

Подивіться питання та відповіді або напишіть нам — відповімо й допишемо документацію.