Готовые сценарии
Интеграции QRTap
Шесть сценариев, которые закрывают почти все запросы: коды на сделки в CRM, QR на чеках, Telegram-бот, тираж из таблицы, no-code-автоматизация и печать в типографии. Для каждого — задача бизнеса, что берёт на себя QRTap и кусок кода, который можно скопировать.
Общее для всех сценариев: ключ в заголовке 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 | plaindowngraded означает: брендирование не прошло проверку декодированием и отдан простой код — тираж всё равно отсканируется. caption проверяется на рекламные формулировки, запрещённые ст. 17 Закона КР «О рекламе» (422 prohibited_content).
Не нашли свой сценарий
- ИИ-ассистент — если систему заменяет живой диалог: MCP-сервер даёт ассистенту 20 инструментов QRTap.
- OpenAPI 3.1 — сгенерируйте клиента под свой язык или импортируйте в Postman: там описаны все 17 маршрутов с телами и ошибками.
- Документация — умные правила по устройству, языку и часам, история назначений, страницы-визитки, ящики отзывов и заявок.
- Поддержка — напишите, какой системы не хватает: мы собираем эти запросы и по ним решаем, что описывать следующим.
Интеграции подчиняются Условиям использования API, оферте и политике конфиденциальности. За содержимое ссылок, на которые ведут ваши коды, отвечаете вы; перепродажа доступа к API и обход лимитов запрещены.