Готовые сценарии

Интеграции QRTap

Шесть сценариев, которые закрывают почти все запросы: коды на сделки в CRM, QR на чеках, Telegram-бот, тираж из таблицы, no-code-автоматизация и печать в типографии. Для каждого — задача бизнеса, что берёт на себя QRTap и кусок кода, который можно скопировать.

CRMPOS и чекиTelegram-ботТаблицыАвтоматизацияТипография

Общее для всех сценариев: ключ в заголовке Authorization: Bearer <ключ> (выпускается в кабинете бесплатно и сразу), база https://app.qrtap.kg, формат — JSON. Ваш идентификатор кладите в external_ref: создание идемпотентно по нему, поэтому синхронизацию можно перезапускать сколько угодно раз, не боясь дубликатов. Полный справочник — в документации, машиночитаемая спека — /openapi.json.

Что можно попробовать бесплатно, а что открывается за деньги. На бесплатном тарифе работает всё, кроме трёх вещей: пакетного создания (/api/v1/codes/bulk), вебхуков сканов (/api/v1/webhooks) и записи умных правил — они отвечают 402 plan_required со ссылкой на тарифы. Объём на бесплатном — 100 запросов в сутки на всё рабочее пространство (сутки считаются по UTC); на «Основном» — 5 000, на «Полном» — 50 000. Значит, сценарии «CRM» и «Telegram-бот» ниже можно собрать и проверить сегодня, а «POS», «Таблицы» и «Автоматизация» упрутся в платные bulk и вебхуки. Цифры — на странице для разработчиков.

CRM: код на сделку и активность по скану

ЗадачаМенеджер отправляет клиенту коммерческое предложение с QR-кодом и хочет знать, посмотрел ли клиент — и когда.

QRTapНа каждую сделку выдаёт свой управляемый код с external_ref = id сделки и присылает вебхук в момент скана — CRM видит реальный контакт, а не догадку.

// 1. Создаём код на сделку. Повторный вызов с тем же external_ref
//    вернёт существующий код — синхронизацию безопасно ретраить.
const res = await fetch("https://app.qrtap.kg/api/v1/codes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.QRTAP_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    target_url: `https://your-crm.example/offer/${deal.id}`,
    label: `КП — ${deal.company}`,
    external_ref: `deal-${deal.id}`,
    group: "partner",
  }),
});
const code = await res.json();
// code.short_url — печатаем в КП; code.png_url — картинка для письма
await crm.saveField(deal.id, "qr_short_url", code.short_url);

// 2. Один раз регистрируем вебхук на сканы
await fetch("https://app.qrtap.kg/api/v1/webhooks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.QRTAP_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://your-crm.example/hooks/qrtap" }),
});
// 201 → { "signing_secret": "whsec_…" } — показывается один раз, сохраните
// 3. Обработчик: проверяем подпись и пишем активность в сделку
import { createHmac, timingSafeEqual } from "node:crypto";

export async function POST(request) {
  const raw = await request.text();
  const expected = createHmac("sha256", process.env.QRTAP_WEBHOOK_SECRET)
    .update(raw)
    .digest("hex");
  const given = (request.headers.get("x-qrtap-signature") ?? "").replace(/^sha256=/, "");
  if (given.length !== expected.length ||
      !timingSafeEqual(Buffer.from(given, "hex"), Buffer.from(expected, "hex"))) {
    return new Response("bad signature", { status: 401 });
  }

  const scan = JSON.parse(raw); // { code_id, external_ref, group, ts, device_type }
  const dealId = scan.external_ref?.replace(/^deal-/, "");
  if (dealId) await crm.addActivity(dealId, `Клиент открыл КП (${scan.device_type})`, scan.ts);
  return new Response("ok"); // ответьте 2xx за 8 секунд
}

Доставка at-least-once — обработчик должен быть идемпотентным. Персональных данных в payload нет: только идентификаторы, время и класс устройства. Шаг 1 (создание кодов) работает и на бесплатном тарифе; шаги 2–3 — вебхуки — требуют платного, на бесплатном регистрация вернёт 402 plan_required.

POS и чеки: отзывы с точек продаж

ЗадачаСеть из десяти точек хочет собирать отзывы с чеков и понимать, какая точка работает лучше — не заказывая новый тираж под каждую акцию.

QRTapПечатает на чеке постоянную короткую ссылку, ведёт её на страницу отзывов и считает сканы по каждой точке отдельно через group.

# 1. Один раз собираем страницу отзывов и наводим на неё коды точек
curl -X POST https://app.qrtap.kg/api/v1/pages \
  -H "Authorization: Bearer $QRTAP_KEY" -H "Content-Type: application/json" \
  -d '{"content":{"segment":"otzyvy","name":"Кофейня «Тандем»",
        "phone":"0555 123 456",
        "reviewLinks":{"twogis":"https://2gis.kg/bishkek/firm/70000001"}}}'
# 201 → { "slug":"cozy-cafe-x1", "public_url":"https://app.qrtap.kg/a/cozy-cafe-x1" }

# 2. Коды на все точки одной партией (до 500 за вызов)
curl -X POST https://app.qrtap.kg/api/v1/codes/bulk \
  -H "Authorization: Bearer $QRTAP_KEY" -H "Content-Type: application/json" \
  -d '[{"target_url":"https://app.qrtap.kg/a/cozy-cafe-x1","external_ref":"pos-01","group":"partner","label":"Чек — Киевская"},
       {"target_url":"https://app.qrtap.kg/a/cozy-cafe-x1","external_ref":"pos-02","group":"partner","label":"Чек — Чуй"}]'
# 201 → { "created": 2, "failed": 0, "data": [ … ] }

# 3. Печатаем на чеке short_url из ответа. Сравнение точек:
curl -H "Authorization: Bearer $QRTAP_KEY" \
  "https://app.qrtap.kg/api/v1/codes?group=partner&include=stats"
# у каждого кода появится поле scans — все счётчики одним запросом

# 4. Сводка по всей сети
curl -H "Authorization: Bearer $QRTAP_KEY" \
  "https://app.qrtap.kg/api/v1/groups/partner/stats"

Акция поменялась — переводите коды на новый адрес через PATCH /api/v1/codes/{id}: напечатанные чеки продолжают работать. Отзывы забирайте из GET /api/v1/reviews?status=pending; пока владелец не опубликовал отзыв, его не видит никто. Шаг 2 использует пакетное создание — платный тариф; на бесплатном создавайте коды по одному через POST /api/v1/codes.

Telegram-бот: QR-код по запросу

ЗадачаСотрудники просят QR-код «прямо сейчас, с телефона», и никто не хочет заходить в кабинет с ноутбука.

QRTapОтдаёт готовый PNG по адресу из png_url — бот пересылает картинку пользователю, не рисуя QR сам.

// Хендлер команды: /qr https://example.com/menu Меню зала
async function onQrCommand(chatId, url, label) {
  const created = await fetch("https://app.qrtap.kg/api/v1/codes", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.QRTAP_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ target_url: url, label }),
  }).then((r) => r.json());

  // Артефакт требует того же ключа — скачиваем и отправляем файлом
  const png = await fetch(`${created.png_url}&size=1080`, {
    headers: { Authorization: `Bearer ${process.env.QRTAP_KEY}` },
  }).then((r) => r.arrayBuffer());

  const form = new FormData();
  form.append("chat_id", String(chatId));
  form.append("caption", `${label}\n${created.short_url}`);
  form.append("document", new Blob([png], { type: "image/png" }), "qr.png");

  await fetch(`https://api.telegram.org/bot${process.env.BOT_TOKEN}/sendDocument`, {
    method: "POST",
    body: form,
  });
}

Отправляйте именно документом, а не фото: Telegram сжимает фотографии, и мелкий код может перестать считываться. Для печати запрашивайте ?format=pdf или ?format=svg.

Таблицы: тираж из CSV одной командой

ЗадачаЕсть выгрузка из 1С или Google Sheets на 300 позиций, и под каждую нужен свой QR-код — вручную это неделя работы.

QRTapПринимает до 500 кодов за вызов и возвращает результат по каждой строке отдельно: одна ошибка не роняет всю партию.

# items.csv:  sku,url,title
#             SMK-P-001,https://example.com/p/1,Кофемолка
#             SMK-P-002,https://example.com/p/2,Термос

import csv, json, os, urllib.request

def post(path, payload):
    request = urllib.request.Request(
        "https://app.qrtap.kg" + path,
        data=json.dumps(payload).encode(),
        headers={"Authorization": "Bearer " + os.environ["QRTAP_KEY"],
                 "Content-Type": "application/json"},
        method="POST")
    with urllib.request.urlopen(request) as response:
        return json.load(response)

rows = list(csv.DictReader(open("items.csv", encoding="utf-8")))
for start in range(0, len(rows), 500):            # партия — максимум 500
    batch = [{"target_url": r["url"], "label": r["title"],
              "external_ref": r["sku"], "group": "equipment"}
             for r in rows[start:start + 500]]
    result = post("/api/v1/codes/bulk", batch)
    print(result["created"], "создано,", result["failed"], "с ошибкой")
    for item in result["data"]:
        if item["ok"]:
            print(item["external_ref"], "→", item["short_url"], item["png_url"])
        else:
            print(item["external_ref"], "ошибка:", item["error"])

Скрипт можно гонять хоть каждый день: external_ref делает создание идемпотентным, повторный запуск не наплодит дубликатов. Обратная синхронизация счётчиков — один запрос GET /api/v1/codes?include=stats. Пакетный маршрут — платный тариф; и помните про суточную квоту: 300 строк — это 1 вызов bulk, но 300 отдельных POST /api/v1/codes — это 300 запросов из вашей суточной квоты на всё рабочее пространство.

No-code: n8n, Make, Zapier

ЗадачаПроцесс собран в n8n, Make или Zapier, программиста в штате нет, а коды нужно выдавать автоматически — например, на каждую новую заявку.

QRTapРаботает обычным HTTP: любой узел «HTTP Request» и любой приёмник вебхуков — никаких плагинов ставить не нужно.

Узел «HTTP Request» — создать код
  Method:  POST
  URL:     https://app.qrtap.kg/api/v1/codes
  Headers: Authorization: Bearer {{$env.QRTAP_KEY}}
           Content-Type: application/json
  Body:    { "target_url": "{{$json.link}}",
             "label": "{{$json.title}}",
             "external_ref": "{{$json.id}}" }
  Ответ:   short_url — вставляйте в письмо или документ
           png_url   — качается тем же заголовком Authorization

Узел «Webhook» — реагировать на скан
  Один раз: POST https://app.qrtap.kg/api/v1/webhooks  {"url": "<адрес вашего вебхука>"}
  Прилетает: { code_id, external_ref, group, ts, device_type }
  Заголовки: X-QRTap-Event: scan
             X-QRTap-Signature: sha256=<hex>   ← проверьте на signing_secret

Если сценарий делает много вызовов подряд, добавьте паузу: при 429 заголовок Retry-After говорит, сколько секунд ждать, а поле scope в теле — что именно кончилось: minute (подождать и продолжить) или day (суточная квота, нужен тариф выше). Заголовки X-RateLimit-* приходят только в ответе 429, в успешных их нет. Сами маршруты управления вебхуками квоту не расходуют, но требуют платного тарифа.

Типография: вектор, логотип и проверка читаемости

ЗадачаТипография просит вектор в фирменных цветах и не готова отвечать за то, что код не отсканируется с готового тиража.

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

# 1. Шаблон дизайна: цвет модулей + логотип в центре (data URI, не URL)
curl -X POST https://app.qrtap.kg/api/v1/design-templates \
  -H "Authorization: Bearer $QRTAP_KEY" -H "Content-Type: application/json" \
  -d '{"name":"Фирменный","module_color":"#16613F",
       "logo":"data:image/png;base64,iVBORw0KGgo…"}'
# 201 → { "id": "…" }

# 2. Код с этим шаблоном
curl -X POST https://app.qrtap.kg/api/v1/codes \
  -H "Authorization: Bearer $QRTAP_KEY" -H "Content-Type: application/json" \
  -d '{"target_url":"https://example.com/menu","label":"Меню",
       "design_template_id":"<id шаблона>"}'

# 3. Файлы для типографии
curl -D headers.txt -o code.pdf -H "Authorization: Bearer $QRTAP_KEY" \
  "https://app.qrtap.kg/api/v1/codes/<id>/qr?format=pdf"
curl -o code.svg -H "Authorization: Bearer $QRTAP_KEY" \
  "https://app.qrtap.kg/api/v1/codes/<id>/qr?format=svg&caption=Меню"
grep -i x-qrtap-qa headers.txt   # branded | downgraded | plain

downgraded означает: брендирование не прошло проверку декодированием и отдан простой код — тираж всё равно отсканируется. caption проверяется на рекламные формулировки, запрещённые ст. 17 Закона КР «О рекламе» (422 prohibited_content).

Не нашли свой сценарий

  • ИИ-ассистент — если систему заменяет живой диалог: MCP-сервер даёт ассистенту 20 инструментов QRTap.
  • OpenAPI 3.1 — сгенерируйте клиента под свой язык или импортируйте в Postman: там описаны все 17 маршрутов с телами и ошибками.
  • Документация — умные правила по устройству, языку и часам, история назначений, страницы-визитки, ящики отзывов и заявок.
  • Поддержка — напишите, какой системы не хватает: мы собираем эти запросы и по ним решаем, что описывать следующим.

Интеграции подчиняются Условиям использования API, оферте и политике конфиденциальности. За содержимое ссылок, на которые ведут ваши коды, отвечаете вы; перепродажа доступа к API и обход лимитов запрещены.

На главную · API · MCP · OpenAPI · Тарифы · Поддержка · Условия API