Интеграция тендеров

Интеграция тендеров: закупки в CRM и своих системах

Схема одна для любой CRM: фоновый воркер на вашем сервере читает ленту закупок по сохранённому курсору и создаёт из новых объектов лиды или сделки штатным API вашей CRM. Напрямую из браузера обращаться к API нельзя — он работает только server-to-server, CORS отключён, а токен даёт доступ к балансу и не должен покидать сервер.

Схема интеграции

Fraim.ru API  ──►  ваш воркер  ──►  API вашей CRM
(лента по         (расписание,      (лиды, сделки,
 курсору)          дедупликация)      задачи)
                       │
                       └──►  ваша БД: последний курсор + обработанные id/version

Три элемента, и все три обязательны. Воркер нужен, потому что API server-to-server. Своя таблица нужна, чтобы помнить курсор и уже обработанные версии. Расписание нужно, потому что закупки появляются постоянно, а не по запросу пользователя.

Почему нельзя обращаться из CRM напрямую

  • CORS отключён. API рассчитан на межсерверное взаимодействие; браузерный запрос из виджета или веб-хука фронтенда просто не пройдёт.
  • Токен — это доступ к балансу. Ключ, попавший в браузер или в мобильное приложение, может быть использован кем угодно и потратит ваши деньги.
  • Нужна память между запусками. Курсор и обработанные версии где-то должны храниться — у CRM для этого нет подходящего места.

Активных токенов может быть до 20 — заведите для интеграции отдельный, чтобы отозвать его, не задев остальные. Начинать удобнее с тестового fraim_test_…: песочница не списывает баланс, а код при переходе в продакшн не меняется — меняется только токен.

Воркер: рабочий пример

Python
import os, time, requests

API = "https://public.fraim.ru/api/v2"
H = {"Authorization": f"Bearer {os.environ['FRAIM_TOKEN']}"}

FILTER = {
    "keywords": ["поставка оборудования"],
    "exception_keywords": ["монтаж"],
    "regions": [1, 2],
    "price": {"from": 300000},
    "status": ["active"],
    "limit": 100,
}

def tick(cursor):
    """Один проход. Возвращает новый курсор — его нужно сохранить."""
    body = {"cursor": cursor} if cursor else FILTER
    r = requests.post(f"{API}/tenders/query", json=body, headers=H, timeout=60)

    if r.status_code == 202:                       # фоновый сбор — повторить позже
        return cursor
    if r.status_code == 429:                       # лимит частоты
        time.sleep(int(r.headers.get("Retry-After", 60)))
        return cursor
    if r.status_code == 409:                       # лента пересобрана: срез уже в теле
        body = r.json()["detail"]
        push_to_crm(body["results"])
        return body["next_cursor"]
    if r.status_code == 402:                       # баланс кончился — не терять курсор
        notify("Fraim.ru: пополните баланс")
        return cursor

    r.raise_for_status()
    data = r.json()
    push_to_crm(data["results"])
    return data["next_cursor"]

Курсор возвращается из каждой ветки, включая ошибочные: потерянный курсор означает повторное чтение выборки с начала — и повторную оплату новых версий объектов.

Дедупликация и обновления

Закупка живёт: меняются сроки, документация, статус. В ленту она приходит снова — с тем же id и новой version. Правило простое:

  • Новый id — создать карточку в CRM.
  • Тот же id, новая version — обновить существующую, а не плодить дубль.
  • Та же пара id + version — пропустить: вы это уже обрабатывали.

Хранить обработанные пары нужно у себя: доставка считается выполненной на стороне API независимо от того, что с объектом сделала ваша интеграция.

Частота опроса

Раз в 5–15 минут закрывает практически любую воронку. Лента по курсору отдаёт всё накопившееся с прошлого раза, поэтому между опросами ничего не теряется — частота влияет только на задержку, а не на полноту.

  • 100 запросов в минуту на аккаунт — ежеминутный опрос тратит один из ста.
  • 20 запросов в секунду по IP — ограничение на всплески; параллельная выгрузка в несколько потоков упирается в него раньше, чем в минутный лимит.
  • Пустой results с непустым next_cursor — «сейчас нового нет», курсор рабочий, опрос бесплатен.

Расход на постоянный мониторинг

Счёт зависит не от частоты опроса, а от того, сколько закупок реально проходит через ваш фильтр. Опросы без новых объектов и повторы той же версии бесплатны; платится только первая доставка версии — от 0,75 ₽ за объект.

Отсюда практический совет: сужайте фильтр, а не частоту. Минус-слова и вилка цены снимают со счёта больше, чем любые ухищрения с расписанием, и одновременно избавляют менеджеров от нерелевантных карточек.

Обновлено 27 августа 2026 г.. Цифры сверяются с документацией API при каждом изменении.
Вопросы

Вопросы об интеграции тендеров

Как подтянуть тендеры в Битрикс24?

Через свой бэкенд: небольшой фоновый воркер по расписанию читает ленту Fraim.ru по сохранённому курсору и создаёт из новых закупок лиды или сделки штатным API CRM. Напрямую из браузера или из формул CRM обращаться к API нельзя: он только server-to-server, CORS отключён, а токен нельзя показывать клиенту.

Есть ли готовое приложение для CRM?

Готового приложения в маркетплейсе нет — Fraim.ru это HTTP-API без SDK-зависимостей, который подключается из любого языка и стека. Практика показывает, что интеграция всё равно пишется под конкретную воронку: какие закупки считать лидом и в какую стадию их класть, у всех по-разному.

Как часто опрашивать API, чтобы не пропустить закупку?

Раз в 5–15 минут более чем достаточно: закупки появляются по мере поступления с площадок, а лента по курсору отдаёт всё накопившееся с прошлого раза — ничего не теряется между опросами. Лимит — 100 запросов в минуту на аккаунт, так что даже ежеминутный опрос тратит один запрос из ста.

Как не создавать дубли карточек в CRM?

Дедуплицируйте по паре id + version: id — сам объект, version — его состояние. Новый id означает новую карточку, тот же id с новой version — обновление существующей. Храните последнюю обработанную версию у себя: API считает доставку выполненной независимо от того, что вы с ней сделали.

Сколько стоит держать мониторинг закупок в CRM?

Платятся только доставленные объекты: первая доставка версии — от 0,75 ₽, цена зависит от суммы пополнения баланса. Опросы, в которых ничего нового нет, бесплатны, повторы той же версии — тоже. То есть счёт зависит от того, сколько закупок реально проходит через ваш фильтр, а не от частоты опроса.

Проверьте на своих данных

Регистрация — почта и пароль, меньше минуты. Тестовый токен выдаётся сразу: без телефона, звонков менеджера и карты.

Получить тестовый токенДокументация