QRFLOW.codes
официальныйСоздавайте QR-коды, перенаправляйте напечатанные динамические коды, называйте ссылки на своём домене и читайте аналитику сканирований.
Что можно делать с QRFLOW Codes MCP?
- Создание динамических QR-кодов — Попросите сгенерировать печатаемый
short_urlдля любого URL-адреса, с возможностью изменить пункт назначения в любое время после печати. - Перенаправление напечатанных кодов — Запросите обновление
destination_dataкода на новый URL-адрес; существующие напечатанные коды продолжат работать без повторной печати. - Получение аналитики сканирований — Запросите разбивку
Scansпо дням, странам или устройствам, чтобы увидеть, как работает напечатанный код. - Приостановка или истечение срока действия кодов — Дайте указание приостановить код или установить дату истечения срока действия, когда кампания или предложение завершится.
- Именование ссылок на вашем домене — Запросите установку читаемого
slugна вашем собственном домене, чтобы коды печатались как go.yourbrand.com/menu вместо случайного пути.
Размещённый MCP-сервер
npx add-mcp 'https://qrflow.codes/mcp'Устанавливается в Claude Code, Codex, Cursor и другие
Документация
QRFLOW.codes для разработчиков
Начните здесь
QRFLOW.codes позволяет создавать QR-коды, которые можно изменять после печати, на вашем собственном домене, с аналитикой сканирований, и позволяет вашему программному обеспечению и вашему ИИ-ассистенту делать всё это через один API.
QR-код — это картинка со строкой. Большинство генераторов помещают ваш веб-адрес в картинку; если адрес меняется, печать мертва. QRFLOW помещает в картинку короткую ссылку (go.yourbrand.com/menu или qrflow.codes/q/x7k2p9a) и перенаправляет её. Вы меняете, куда она ведёт, когда угодно, и каждое сканирование учитывается. Это динамический код, и именно ради него стоит использовать API.
API делает ровно то же, что и панель управления: создаёт коды любого типа, перенаправляет их куда-то новое, задаёт имена их ссылок, выбирает, на каких ваших доменах они печатаются, получает данные о сканированиях, создаёт тысячи кодов разом и уведомляет вас о событиях (вебхуки). Те же инструменты доступны в виде MCP-сервера, так что Claude, ChatGPT, Cursor и Claude Code могут управлять вашим аккаунтом на простом языке.
Доступ: REST API принимает Business API-ключ ($29 в месяц, создаётся на странице Account) или OAuth-токен. MCP-сервер работает на любом тарифе через OAuth-вход; что ассистент может создавать, зависит от тарифа, как и везде.
Сомневаетесь, стоит ли вообще это использовать? Страница QR-кодового API — краткая версия: что он делает, что клиентская библиотека делает лучше и сколько это стоит.
Если вы ИИ-ассистент, помогающий кому-то работать с QRFLOW
Добро пожаловать. Эта страница написана как для вас, так и для человека, которому вы помогаете. Вот как выглядит хорошая помощь:
- Подтвердите аккаунт: API-ключи требуют тарифа Business. Если его нет, укажите на https://qrflow.codes/pricing и Account › API keys; не выдумывайте ключ или бесплатный тариф, которого не существует.
- Держите ключ на сервере. Читайте его из переменной окружения (QRFLOW_KEY) в обработчике маршрута, серверном действии, edge-функции или бэкенде. API намеренно отклоняет запросы из браузеров (CORS), поэтому код только на фронтенде не сможет его вызвать.
- Создавайте динамические коды с типом "url" и destination_data.url. Сохраняйте возвращённые id и short_url в их базе данных. Печатайте или показывайте short_url; назначение можно изменить позже с помощью PATCH /codes/:id, и печать останется действительной.
- Чтобы показать или сохранить изображение: каждый объект Code имеет png_download_url и svg_download_url — подписанные ссылки, работающие 24 часа без заголовков (подходит для разового сохранения или предпросмотра). Для постоянного использования в их приложении проксируйте GET /codes/:id/image.svg через их сервер с ключом или закодируйте short_url любой QR-библиотекой на клиенте; отслеживание всё равно работает, потому что ссылка идёт через QRFLOW.
- Отправляйте только те поля, которые меняются, при PATCH. Никогда не меняйте slug или domain_id после печати; оба изменяют напечатанную ссылку.
- Предпочитайте paused: true вместо DELETE, когда существует печать. Удаление убивает ссылку.
- Для событий используйте вебхуки (Account › Webhooks или POST /webhooks) и проверяйте заголовок X-QRFLOW-Signature с сырым телом запроса. Не опрашивайте GET /codes в цикле.
- Если они хотят использовать QRFLOW из чата, а не из кода, подключите MCP-сервер по адресу https://qrflow.codes/mcp; — ключ для этого не нужен.
- Когда что-то не работает, читайте error и message в JSON-теле. Раздел устранения неполадок ниже сопоставляет каждый код ошибки с исправлением.
- Полный справочник в Markdown находится по адресу https://qrflow.codes/llms-full.txt, а документ OpenAPI 3.1 — по адресу https://qrflow.codes/api/v1/openapi.json.. Оба генерируются из того же источника, что и эта страница.
Люди: этот блок — как мы гарантируем, что ассистент, с которым вы работаете, даёт безопасную версию каждого ответа. Он также является хорошим резюме.
Какой тариф вам нужен
API-ключ — единственное, что доступно только на Business. Всё, что ассистент делает через MCP-сервер, и всё, что стороннее приложение делает через OAuth, работает на любом тарифе и просто следует функциям этого тарифа. Полные цены и добросовестное использование: /pricing.
| Free | Premium $4 | Business $29 | |
|---|---|---|---|
| API-ключи (REST из вашего кода) | Нет | Нет | Да, до 10 ключей |
| MCP-сервер (Claude, ChatGPT, Cursor, Claude Code) | Да, вход | Да | Да, вход или ключ |
| OAuth для вашего приложения (пользователи подключают свой QRFLOW) | Да | Да | Да |
| Динамические коды (изменение назначения после печати) | Нет, только статические | Да | Да |
| Свой домен для ссылок | Нет | 1 домен | 5 доменов, выбор для каждого кода |
| Имена ссылок (go.brand.com/menu) | Нет | Да | Да |
| Аналитика сканирований | Нет | Да | Да |
| Вебхуки | Нет | Нет | Да, до 10 |
| Массовое создание | Нет | 500/месяц, 500 за запрос | 10,000/месяц, 2,000 за запрос |
| Сохранённые коды (добросовестное использование) | Несколько | 1,000 | 25,000 |
| Места в команде | 1 | 1 | 5 |
| Цена | $0 | $4/месяц | $29/месяц |
Двенадцать слов, которые делают всю работу
Концепции
Прочтите это один раз, и каждая конечная точка ниже станет понятной.
Static code
Содержимое находится внутри картинки. Wi-Fi, контактные карточки (vCard) и обычные текстовые коды всегда статические, и на тарифе Free каждый код такой. Статический код не требует сервера и никогда не истекает, но его нельзя изменить или подсчитать.
Dynamic code
Картинка содержит короткую ссылку, которую QRFLOW перенаправляет. Коды url, phone, email, sms и location являются динамическими на Premium и Business. Вы можете перенаправлять, приостанавливать, устанавливать срок действия, переименовывать и подсчитывать их, не трогая печать.
short_url
Точная строка, закодированная в динамическом коде, и то, что нужно печатать. Это https://qrflow.codes/q/<short_code> пока вы не подключите домен, затем https://<your domain>/<slug or short_code>.. Каждый объект Code содержит её.
short_code
Семь случайных символов, уникальных для каждого кода, назначаются при создании и никогда не меняются. Запасной путь, когда у кода нет имени ссылки.
slug (link name)
Читаемый путь на вашем собственном домене: go.example.com/menu. От 3 до 40 строчных букв, цифр и дефисов, уникальный в пределах вашего аккаунта, только с подключённым доменом. Установите его до печати: его изменение меняет напечатанную ссылку.
Link domain
Имя хоста, которым вы владеете (go.example.com), указывающее на QRFLOW через CNAME и проверенное на странице Account. Premium получает один; Business получает пять и может выбирать для каждого кода с помощью domain_id. Самый старый активный домен используется по умолчанию.
Kind, type and subtype
type — это кодировка: url, text, wifi, vcard, email, phone, sms, location. kind — более дружелюбное имя для того, что нужно людям (instagram, googlereview, whatsapp, pdf, menu, appstore,...). Большинство kinds — это url-коды с установленным destination_data.subtype. GET /catalog перечисляет каждый kind с его полями; kind на Code говорит вам, какой это.
destination_data
Поля для типа, как строки: { url } для веб-сайта, { ssid, password, encryption } для Wi-Fi, { placeId } для отзыва Google, { handle } для Instagram. На динамическом коде вы можете заменить их в любое время.
Scans
Каждое перенаправление записывает тип устройства, страну, город, реферера, браузер, ОС и язык из самого запроса, плюс односторонний ежедневный хэш для подсчёта уникальных посетителей. Файлы cookie не устанавливаются, IP-адрес не хранится. scans на Code — это общее количество за всё время; GET /codes/:id/scans разбивает его по деталям.
Source
Каждый код помнит, что его создало: dashboard, api:<key name>, mcp, canva или bulk. Это отображается в панели управления и в полезных нагрузках вебхуков, так что вы можете отличить коды вашей интеграции от созданных вручную.
Workspace
Владелец Business может пригласить до четырёх коллег. Ключи и вебхуки принадлежат аккаунту владельца; коды, созданные кем-либо в рабочем пространстве, видны всей команде.
Пять минут
Быстрый старт
Получите ключ
- На тарифе Business откройте Account › API keys.
- Назовите его по назначению ("Бэкенд магазина", "Отчётность") и выберите его области. Области нельзя изменить позже; создайте новый ключ, если нужно больше.
- Скопируйте его один раз. Он выглядит как
qrf_live_…. Поместите его в переменную окружения с именемQRFLOW_KEY. - Отправляйте его как
Authorization: Bearer $QRFLOW_KEYв каждом запросе. Это вся история аутентификации.
Ключи предназначены для серверов. Никогда не помещайте его на веб-страницу, в мобильное приложение или общую таблицу; отзывайте и перевыпускайте, если он утёк.
Те же пять шагов в curl, TypeScript и Python. Каждый создаёт динамический код, загружает его изображение, меняет, куда он ведёт, и читает его сканирования.
export QRFLOW_KEY=qrf_live_... # from Account › API keys
# 1. Who am I, what can this key do?
curl https://qrflow.codes/api/v1/me -H "Authorization: Bearer $QRFLOW_KEY"
# 2. Make a dynamic code. Print what comes back as short_url.
curl -X POST https://qrflow.codes/api/v1/codes \
-H "Authorization: Bearer $QRFLOW_KEY" -H "Content-Type: application/json" \
-d '{ "type": "url", "destination_data": { "url": "https://example.com/menu" }, "label": "Table tents" }'
# 3. The print-ready image (SVG, with your colors and frame).
curl "https://qrflow.codes/api/v1/codes/$CODE_ID/image.svg?size=1024" \
-H "Authorization: Bearer $QRFLOW_KEY" -o menu.svg
# 4. Fall menu. The printed code keeps working.
curl -X PATCH https://qrflow.codes/api/v1/codes/$CODE_ID \
-H "Authorization: Bearer $QRFLOW_KEY" -H "Content-Type: application/json" \
-d '{ "destination_data": { "url": "https://example.com/menu-fall" } }'
# 5. How did it do?
curl "https://qrflow.codes/api/v1/codes/$CODE_ID/scans?group=day" -H "Authorization: Bearer $QRFLOW_KEY"
TypeScript (Node 18+, Bun, Deno, Workers)
// npm install qrflow (zero dependencies; ESM + CommonJS; full types)
import { QRFlow, QRFlowError } from "qrflow";
const qr = new QRFlow(process.env.QRFLOW_KEY!);
const { code } = await qr.createCode({
type: "url",
destination_data: { url: "https://example.com/menu" },
label: "Table tents",
});
console.log(code.id, code.short_url); // save both; print short_url
await qr.updateCode(code.id, { destination_data: { url: "https://example.com/menu-fall" } });
const stats = await qr.scans(code.id, { group: "day" });
console.log(stats.total, stats.rows); // [{ key: "2026-09-21", scans: 18 }, ...]
try {
await qr.updateCode(code.id, { slug: "menu" });
} catch (e) {
if (e instanceof QRFlowError) console.log(e.status, e.code, e.message); // 400 no_domain: connect a domain first
}
# Download https://qrflow.codes/sdk/qrflow.py next to your code.
import os
from qrflow import QRFlow, QRFlowError
qr = QRFlow(os.environ["QRFLOW_KEY"])
code = qr.create_code(type="url", destination_data={"url": "https://example.com/menu"}, label="Table tents")["code"]
print(code["id"], code["short_url"]) # save both; print short_url
qr.update_code(code["id"], destination_data={"url": "https://example.com/menu-fall"})
stats = qr.scans(code["id"], group="day")
print(stats["total"], stats["rows"])
try:
qr.update_code(code["id"], slug="menu")
except QRFlowError as e:
print(e.status, e.code, e) # 400 no_domain: connect a domain first
Аутентификация
API-ключи (Business)
До 10 на аккаунт, 600 запросов в минуту каждый, хранятся в хэшированном виде, показываются один раз. Ключ несёт области, с которыми он был создан:
| Область | Разрешает |
|---|---|
| profile | GET /me: тариф, функции, лимиты. Есть у каждого ключа. |
| codes:read | Список и чтение кодов, загрузка изображений. |
| codes:write | Создание, изменение, превращение в динамические, удаление, массовое создание. |
| analytics:read | GET /codes/:id/scans. |
| domains:read | GET /domains (нужно для осмысленного использования domain_id). |
| webhooks:manage | Список, создание, тестирование и удаление вебхуков. |
OAuth 2.0 (любой тариф, для приложений и ассистентов)
Когда коды должны принадлежать аккаунтам ваших пользователей, а не вашим, или когда клиентом является чат-ассистент, используйте OAuth. Клиенты регистрируют себя сами; PKCE S256 обязателен для публичных клиентов; токены могут быть привязаны к MCP-серверу с помощью resource=. Рецепт OAuth проводит через весь процесс.
| Конечная точка | URL | Примечания |
|---|---|---|
| Авторизация | https://qrflow.codes/oauth/authorize | Отправьте пользователя сюда; он входит и нажимает Разрешить. |
| Токен | https://qrflow.codes/api/oauth/token | Гранты authorization_code и refresh_token. Токены доступа живут 1 час, токены обновления — 90 дней. |
| Отзыв | https://qrflow.codes/api/oauth/revoke | RFC 7009. Пользователи также могут отключиться в Account › Connected apps. |
| Регистрация клиента | https://qrflow.codes/api/oauth/register | Динамическая регистрация RFC 7591, аккаунт не нужен. Публичные клиенты получают dyn_ client_id и должны использовать PKCE S256. |
| Обнаружение | https://qrflow.codes/.well-known/oauth-authorization-server | RFC 8414. Документ ресурса MCP находится по адресу /.well-known/oauth-protected-resource. |
Токены доступа живут 1 час, токены обновления — 90 дней. Пользователи видят подключённые приложения в Account › Connected apps и могут отключиться в любое время. Токен, выпущенный для https://qrflow.codes/mcp, отклоняется на /api/v1, и наоборот.
То, о чём люди действительно спрашивают
Рецепты сборки
Каждый рецепт полный и скопирован прямо из рабочего кода. Выберите тот, который соответствует вашему стеку; форма всегда одна и та же: серверный вызов с ключом, сохранение id и short_url, показ изображения.
- Next.js
- Показ QR без проксирования
- Express или любой Node-сервер
- Cloudflare Workers, Vercel Edge, Deno Deploy, Supabase Edge Functions
- Python
- Один QR-код на заказ, стол, товар, билет или событие
- Изменение того, куда ведёт напечатанный код
- Печать кодов на вашем собственном домене
- График сканирований в вашей собственной админке
- Получение вебхуков в Next.js и их проверка
- Получение вебхуков в Python
- Тысячи кодов из CSV
- Позвольте вашим пользователям подключать свой собственный аккаунт QRFLOW (OAuth)
- Zapier, Make, n8n
Next.js: маршрут, который создаёт код, и маршрут, который его показывает
Когда: У вас есть приложение Next.js (App Router), и вы хотите кнопку, которая создаёт QR-код, и страницу, которая его отображает.
- Поместите ваш ключ в .env.local как QRFLOW_KEY. Никогда не добавляйте префикс NEXT_PUBLIC_.
- Добавьте POST-обработчик маршрута, который создаёт код и возвращает id и short_url.
- Добавьте GET-маршрут, который проксирует изображение, чтобы браузер никогда не видел ключ.
- Сохраните id и short_url в вашей собственной записи (заказ, стол, товар, событие).
import { NextResponse } from "next/server";
export async function POST(req: Request) {
const { url, label } = await req.json();
const r = await fetch("https://qrflow.codes/api/v1/codes", {
method: "POST",
headers: { Authorization: \`Bearer ${process.env.QRFLOW_KEY}\`, "Content-Type": "application/json" },
body: JSON.stringify({ type: "url", destination_data: { url }, label }),
});
const data = await r.json();
if (!r.ok) return NextResponse.json(data, { status: r.status }); // { error, message }
return NextResponse.json({ id: data.code.id, short_url: data.code.short_url });
}
// Proxies the SVG so the key stays on the server. Check that the signed-in
// user owns this id before you serve it, or anyone with an id can fetch it.
export async function GET(_: Request, { params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const r = await fetch(\`https://qrflow.codes/api/v1/codes/${id}/image.svg?size=1024\`, {
headers: { Authorization: \`Bearer ${process.env.QRFLOW_KEY}\` },
});
return new Response(r.body, {
status: r.status,
headers: { "Content-Type": "image/svg+xml", "Cache-Control": "private, max-age=3600" },
});
}
<img src={\`/api/qr/${code.id}/image\`} alt={\`QR code for ${code.label}\`} width={256} height={256} />
<a href={code.short_url}>{code.short_url}</a>
- Серверные действия работают так же: вызывайте fetch с ключом внутри действия.
- Для Pages Router тот же код идёт в pages/api/qr.ts с req/res.
Показ QR без проксирования: рендерите short_url сами
Когда: Вы хотите изображение в браузере немедленно, и вам не нужны рамки или логотип QRFLOW на нём. Любая QR-библиотека подойдет, потому что код И ЕСТЬ короткая ссылка
import QRCode from "qrcode"; // npm i qrcode
// short_url came back from POST /codes. Encode it as-is.
const dataUrl = await QRCode.toDataURL(code.short_url, { width: 512, margin: 2 });
// <img src={dataUrl} /> scans go through QRFLOW, so analytics and re-pointing still work.
- Это самый быстрый путь для предпросмотра. Для печати скачайте /codes/:id/image.svg: он сохраняет выбранные цвета, рамку, подписи и логотип, и это вектор.
- Если позже вы измените slug или domain_id, short_url изменится; перерендерите.
Express или любой Node-сервер
Когда: обычный Node-бэкенд.
import express from "express";
const app = express();
app.use(express.json());
const H = { Authorization: \`Bearer ${process.env.QRFLOW_KEY}\`, "Content-Type": "application/json" };
app.post("/qr", async (req, res) => {
const r = await fetch("https://qrflow.codes/api/v1/codes", {
method: "POST", headers: H,
body: JSON.stringify({ type: "url", destination_data: { url: req.body.url }, label: req.body.label }),
});
res.status(r.status).json(await r.json());
});
app.get("/qr/:id.svg", async (req, res) => {
const r = await fetch(\`https://qrflow.codes/api/v1/codes/${req.params.id}/image.svg\`, { headers: H });
res.status(r.status).type("image/svg+xml").send(await r.text());
});
app.listen(3000);
Cloudflare Workers, Vercel Edge, Deno Deploy, Supabase Edge Functions
Когда: среда выполнения только с fetch, без встроенных модулей Node.
export default {
async fetch(req: Request, env: { QRFLOW_KEY: string }) {
const { url, label } = await req.json();
const r = await fetch("https://qrflow.codes/api/v1/codes", {
method: "POST",
headers: { Authorization: \`Bearer ${env.QRFLOW_KEY}\`, "Content-Type": "application/json" },
body: JSON.stringify({ type: "url", destination_data: { url }, label }),
});
return new Response(r.body, { status: r.status, headers: { "Content-Type": "application/json" } });
},
};
Deno.serve(async (req) => {
const { url, label } = await req.json();
const r = await fetch("https://qrflow.codes/api/v1/codes", {
method: "POST",
headers: { Authorization: \`Bearer ${Deno.env.get("QRFLOW_KEY")}\`, "Content-Type": "application/json" },
body: JSON.stringify({ type: "url", destination_data: { url }, label }),
});
return new Response(await r.text(), { status: r.status, headers: { "Content-Type": "application/json" } });
});
// supabase secrets set QRFLOW_KEY=qrf_live_...
- npm-пакет
qrflow\использует только fetch и WebCrypto, поэтому работает во всех этих средах без изменений.
Python: FastAPI, Flask, Django, скрипт
Когда: ваш бэкенд на Python.
import os
from fastapi import FastAPI, HTTPException, Response
from qrflow import QRFlow, QRFlowError # https://qrflow.codes/sdk/qrflow.py
app = FastAPI()
qr = QRFlow(os.environ["QRFLOW_KEY"])
@app.post("/qr")
def make_qr(url: str, label: str | None = None):
try:
code = qr.create_code(type="url", destination_data={"url": url}, label=label)["code"]
except QRFlowError as e:
raise HTTPException(e.status, {"error": e.code, "message": str(e)})
return {"id": code["id"], "short_url": code["short_url"]}
@app.get("/qr/{code_id}.svg")
def qr_image(code_id: str):
import urllib.request
req = urllib.request.Request(qr.image_url(code_id), headers={"Authorization": f"Bearer {os.environ['QRFLOW_KEY']}"})
with urllib.request.urlopen(req) as r:
return Response(r.read(), media_type="image/svg+xml")
Один QR-код на заказ, столик, товар, билет или событие
Когда: каждой строке в одной из ваших таблиц нужен свой код, создаваемый автоматически.
- Добавьте два столбца в таблицу: qrflow_code_id (uuid) и qr_short_url (text).
- При создании строки отправьте POST /codes с публичным URL строки и меткой, которая ее называет («Заказ 10432», «Столик 7»). Сохраните id и short_url.
- Когда страница строки переезжает (новый домен, новый путь), отправьте PATCH destination_data. Напечатанные коды продолжат работать.
- Когда строка выводится из эксплуатации, отправьте PATCH { paused: true }, если что-то было напечатано; DELETE — только если ничего не печаталось.
- Нужны тысячи кодов сразу (меню на каждый столик для 300 ресторанов)? Используйте POST /codes/bulk порциями и сопоставьте возвращенные коды со строками по метке или порядку.
const { code } = await qr.createCode({
type: "url",
destination_data: { url: \`https://example.com/orders/${order.id}\` },
label: \`Order ${order.number}\`,
});
await db.orders.update(order.id, { qrflow_code_id: code.id, qr_short_url: code.short_url });
- Добросовестное использование — 25 000 сохраненных кодов на тарифе Business; API останавливается на вдвое большем количестве. Если вам нужен код на каждый чек навсегда, сначала свяжитесь с нами: hello@qrflow.codes.
Изменение назначения напечатанного кода
Когда: кампания завершилась, страница переехала, PDF заменен, сезон сменился.
curl -X PATCH https://qrflow.codes/api/v1/codes/$CODE_ID \
-H "Authorization: Bearer $QRFLOW_KEY" -H "Content-Type: application/json" \
-d '{ "destination_data": { "url": "https://example.com/spring" } }'
Приостановите его или задайте дату окончания
# Scans show a "paused" page instead of redirecting
curl -X PATCH https://qrflow.codes/api/v1/codes/$CODE_ID -H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" -d '{ "paused": true }'
# Stops working after the date; null clears it
curl -X PATCH https://qrflow.codes/api/v1/codes/$CODE_ID -H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" -d '{ "expires_at": "2026-12-31T23:59:59Z" }'
- Только динамические коды можно перенаправлять. Код url, созданный на бесплатном аккаунте, или код Wi-Fi/vCard/текста отвечает 400 not_dynamic. Для кода url/телефона/email/sms/местоположения на платном тарифе POST /codes/:id/dynamic конвертирует его, и вам нужно перерендерить и перепечатать, потому что картинка меняется.
- Сканер увидит новый адрес назначения при следующем сканировании. Кэша, который нужно ждать, нет.
Печать кодов на вашем собственном домене
Когда: вы хотите видеть go.example.com/menu в коде вместо qrflow.codes/q/x7k2p9a.
- На странице Account, в разделе Your own link domain, добавьте go.example.com и создайте CNAME, который вам покажут, у вашего DNS-провайдера. Проверка обычно завершается за несколько минут.
- С этого момента short_url каждого нового динамического кода использует этот домен. Существующие коды тоже переключаются: их картинка кодировала qrflow.codes/q/..., который продолжает перенаправлять, так что ничего напечатанное не ломается.
- Давайте кодам читаемые имена с помощью slug: PATCH { "slug": "menu" } создает go.example.com/menu. Делайте это до печати.
- На тарифе Business с несколькими доменами GET /domains перечисляет их с id; передавайте domain_id в POST или PATCH, чтобы выбрать для каждого кода.
Назовите ссылку и выберите домен
curl https://qrflow.codes/api/v1/domains -H "Authorization: Bearer $QRFLOW_KEY"
# { "default_base": "https://go.example.com", "domains": [ { "id": "…", "host": "go.example.com", "is_default": true, … }, { "id": "…", "host": "qr.example.fr", … } ] }
curl -X PATCH https://qrflow.codes/api/v1/codes/$CODE_ID -H "Authorization: Bearer $QRFLOW_KEY" -H "Content-Type: application/json" \
-d '{ "slug": "menu", "domain_id": "<id of qr.example.fr>" }'
# short_url is now https://qr.example.fr/menu
График сканирований в вашей собственной админке
Когда: вы хотите видеть сканирования в день, по странам или по устройствам рядом со своими цифрами.
const stats = await qr.scans(code.id, { from: "2026-09-01", to: "2026-09-30", group: "day" });
// stats.total -> 412
// stats.rows -> [{ key: "2026-09-01", scans: 18 }, { key: "2026-09-02", scans: 25 }, ...]
// Feed rows straight into Recharts, Chart.js, or a <table>.
const byCountry = await qr.scans(code.id, { group: "country" }); // [{ key: "US", scans: 300 }, { key: "MX", scans: 41 }]
const byDevice = await qr.scans(code.id, { group: "device" }); // mobile, desktop, tablet
- Один запрос покрывает до 92 дней; для более длинных диапазонов используйте цикл. Даты в UTC.
- Для живых цифр без опроса подпишите вебхук на событие scan: вы получите каждое сканирование с деталями пачками каждые несколько минут.
Получение вебхуков в Next.js и их проверка
Когда: вы хотите знать, когда код сканируется или изменяется, в своей базе данных, почти в реальном времени.
- Создайте вебхук на Account › Webhooks или через POST /webhooks. Скопируйте секрет (whsec_...) один раз в QRFLOW_WEBHOOK_SECRET.
- Читайте сырое тело как текст перед парсингом; подпись покрывает точные байты.
- Проверьте, затем переключайтесь по событию. Отвечайте 2xx быстро; медленную работу делайте после ответа или в очереди.
- Нажмите Test на вебхуке, чтобы получить подписанный ping и подтвердить подключение.
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(raw: string, header: string, secret: string): boolean {
const t = /t=(\d+)/.exec(header)?.[1], v1 = /v1=([a-f0-9]+)/.exec(header)?.[1];
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = createHmac("sha256", secret).update(\`${t}.${raw}\`).digest("hex");
return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
export async function POST(req: Request) {
const raw = await req.text();
if (!verify(raw, req.headers.get("x-qrflow-signature") ?? "", process.env.QRFLOW_WEBHOOK_SECRET!)) {
return new Response("bad signature", { status: 401 });
}
const evt = JSON.parse(raw) as { id: string; event: string; created_at: string; data: any };
// evt.id is stable across retries: store it and skip duplicates.
switch (evt.event) {
case "scan": // evt.data.scans[]: code_id, label, slug, scanned_at, device, country, city, referrer, browser, os, language
break;
case "code.created": // evt.data.code, evt.data.source
case "code.updated": // evt.data.code, evt.data.changed[]
case "code.deleted": // evt.data.code { id, label, short_code, slug }
break;
case "ping": // the Test button
break;
}
return new Response(null, { status: 204 });
}
- Локально откройте dev-сервер через туннель (cloudflared tunnel --url http://localhost:3000, или ngrok) и используйте этот https URL для вебхука, пока разрабатываете.
- npm-пакет делает это за вас:
import { parseWebhook } from "qrflow"\проверяет и парсит одним вызовом (WebCrypto, поэтому работает и в Workers, и в Deno). Python-клиент включает verify_webhook.
Получение вебхуков в Python
Когда: Flask, FastAPI или Django принимают те же события.
import os, json
from flask import Flask, request, abort
from qrflow import verify_webhook # https://qrflow.codes/sdk/qrflow.py
app = Flask(__name__)
@app.post("/qrflow")
def hook():
raw = request.get_data() # bytes, before any parsing
if not verify_webhook(raw, request.headers.get("X-QRFLOW-Signature", ""), os.environ["QRFLOW_WEBHOOK_SECRET"]):
abort(401)
evt = json.loads(raw)
if evt["event"] == "scan":
for s in evt["data"]["scans"]:
print(s["code_id"], s["scanned_at"], s["country"], s["device"])
return "", 204
Тысячи кодов из CSV
Когда: код на каждый SKU, место, инвентарный номер, рассылку.
import { parse } from "csv-parse/sync";
import { readFileSync } from "node:fs";
const rows = parse(readFileSync("skus.csv"), { columns: true }) as Array<{ sku: string; url: string }>;
const out: Array<{ sku: string; id: string; short_url: string }> = [];
for (let i = 0; i < rows.length; i += 2000) { // Business: 2,000 per request
const chunk = rows.slice(i, i + 2000);
const { codes, rejected, remaining_this_month } = await qr.bulkCreate(
chunk.map((r) => ({ destination: r.url, label: r.sku })),
);
codes.forEach((c, j) => out.push({ sku: chunk[j].sku, id: c.id, short_url: c.short_url }));
if (rejected.length) console.warn(rejected); // rows that were not web addresses
console.log(remaining_this_month, "left this month");
}
- Bulk создает только динамические url-коды, все с одинаковыми цветами. Коды возвращаются в том порядке, в котором вы их отправили, минус отклоненные строки; при сомнениях сопоставляйте по метке.
- Вебхуки получают одно событие code.created на bulk-запрос с codes[] вместо одного на каждый код.
Позвольте пользователям подключать свой аккаунт QRFLOW (OAuth)
Когда: вы создаете продукт для других людей и хотите, чтобы коды попадали в их аккаунты QRFLOW, а не в ваш.
- Зарегистрируйте клиент один раз: POST https://qrflow.codes/api/oauth/register с client_name и redirect_uris. Вы получите client_id (и client_secret для конфиденциальных клиентов).
- Отправьте пользователя на /oauth/authorize с response_type=code, client_id, redirect_uri, scope, state и PKCE (code_challenge, code_challenge_method=S256).
- Обменяйте код на /api/oauth/token. Сохраните refresh token; access-токены живут час.
- Вызывайте /api/v1 с Authorization: Bearer <access_token>. Все работает точно так же, как с ключом, в рамках тарифа пользователя.
curl -X POST https://qrflow.codes/api/oauth/register -H "Content-Type: application/json" \
-d '{ "client_name": "Acme Menus", "redirect_uris": ["https://app.example.com/oauth/qrflow"], "token_endpoint_auth_method": "none" }'
# { "client_id": "dyn_…", "redirect_uris": [...], "grant_types": ["authorization_code","refresh_token"], … }
https://qrflow.codes/oauth/authorize?response_type=code&client_id=dyn_…&redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth%2Fqrflow
&scope=profile%20codes%3Aread%20codes%3Awrite%20analytics%3Aread&state=…&code_challenge=…&code_challenge_method=S256
- Scopes — те же шесть, что и у API-ключей. Запрашивайте минимум, что вам нужно; экран согласия их перечисляет.
- Если ваше приложение — чат-ассистент или агент, добавьте resource=https://qrflow.codes/mcp в authorize-запрос и общайтесь с MCP-сервером вместо этого; токен будет привязан к нему.
Zapier, Make, n8n: вообще без кода
Когда: вы хотите, чтобы сканирования или новые коды попадали в таблицу, Slack-канал или CRM.
- Создайте catch-hook триггер (Zapier: Webhooks by Zapier › Catch Hook; Make: Custom webhook; n8n: Webhook node) и скопируйте его https URL.
- На Account › Webhooks добавьте этот URL и выберите события. Нажмите Test; ping появится в инструменте и даст ему форму полезной нагрузки.
- Сопоставьте data.scans[] (для scan) или data.code (для code.*) с вашей таблицей, сообщением или записью.
- Чтобы создавать коды из этих инструментов, используйте их HTTP-модуль против POST /codes с заголовком Authorization. Храните ключ в хранилище учетных данных инструмента.
- Эти инструменты не могут проверить подпись. URL, который они вам дают, невозможно угадать — это ваша защита; не публикуйте его нигде.
Vibe-кодинг
Промпты для вставки
Помощники по кодингу делают правильные вещи, когда им заранее объясняют правила. Эти промпты несут правила. Вставьте один, заполните скобки, и помощник прочитает Markdown-справочник, прежде чем написать строку кода.
Добавьте QR-коды в мое приложение
Claude, ChatGPT, Cursor, Codex, Windsurf, Copilot Chat: вставьте в чат
Add QR codes to this project using the QRFLOW.codes API.
Read https://qrflow.codes/llms-full.txt before writing code; it is the complete reference.
Rules:
- The API key is in the environment variable QRFLOW_KEY. It must only be used server-side (route handler, server action, edge function). Never expose it to the browser.
- Create dynamic codes: POST https://qrflow.codes/api/v1/codes with { "type": "url", "destination_data": { "url": ... }, "label": ... }.
- Save the returned code.id and code.short_url on my record. short_url is what gets printed or displayed.
- Show the image by proxying GET /codes/:id/image.svg through my server, or by encoding short_url with a QR library on the client.
- Handle errors from the JSON body: { "error", "message" }. Map 402 to "upgrade needed", 429 to a retry with the Retry-After header.
What I want: [describe the feature, e.g. "every event in my events table gets a QR code that opens its public page; show it on the event admin page with a download button"].
Обучите ваш репозиторий QRFLOW
Положите в CLAUDE.md, AGENTS.md, .cursorrules или .github/copilot-instructions.md
## QR codes (QRFLOW.codes)
- Docs: https://qrflow.codes/llms-full.txt (Markdown), https://qrflow.codes/api/v1/openapi.json (OpenAPI 3.1).
- Base URL https://qrflow.codes/api/v1, header Authorization: Bearer $QRFLOW_KEY. Server-side only.
- Codes are created with POST /codes { type: "url", destination_data: { url }, label }. Store code.id and code.short_url.
- Change the destination with PATCH /codes/:id { destination_data: { url } }. Never change slug/domain_id after printing.
- Image: GET /codes/:id/image.svg (needs the key). Prefer paused: true over DELETE when a print exists.
- Webhooks arrive as POST with X-QRFLOW-Signature (t=,v1=HMAC-SHA256 of "t.rawBody"); verify with the raw body.
В Lovable, Bolt, v0, Replit и других конструкторах приложений
Конструкторы с приоритетом фронтенда, которые дают вам бэкенд (Supabase, serverless-функции)
Integrate QRFLOW.codes QR codes. The API refuses browser calls, so create a backend function (Supabase Edge Function / serverless function) that holds the secret QRFLOW_KEY and calls POST https://qrflow.codes/api/v1/codes with { "type": "url", "destination_data": { "url": "<the page URL>" }, "label": "<name>" }. Return code.id and code.short_url to the UI and save them in the database. Render the QR in the UI by encoding short_url with a QR library; add a "Download for print" button that fetches /codes/:id/image.svg through the same backend function. Reference: https://qrflow.codes/llms-full.txt
Кастомный GPT, который управляет моими кодами
ChatGPT › Create a GPT › Actions
Import from URL: https://qrflow.codes/api/v1/openapi.json
Authentication: API Key › Bearer › paste a Business key with the scopes you want the GPT to have.
Then the GPT can list, create, re-point and report on your codes. For a no-setup version, add the MCP connector instead (Developer mode › Plugins › https://qrflow.codes/mcp).
Что сказать, когда коннектор подключен
Claude, ChatGPT, Claude Code с подключенным MCP-сервером QRFLOW
"Make a QR code for https://example.com/fall-menu, call it Fall menu, frame caption 'Scan for menu'."
"Which of my codes got the most scans this month? Show a breakdown by country for the top one."
"Point the 'Lobby poster' code at https://example.com/events/october."
"Name the 'Business card' code's link 'hi' on my domain."
"Pause every code with 'Summer' in the label."
"Make 40 codes, one per table, going to https://example.com/order?table=1 through 40."
"Show me the PNG of the 'Front door' code."
MCP-сервер
Использование из Claude, ChatGPT, Cursor и Claude Code
QRFLOW — это MCP-сервер по адресу https://qrflow.codes/mcp. Подключите его один раз, войдите, и затем говорите что-то вроде «сделай QR-код для нашей страницы осеннего меню, названный menu на моем домене», «перенаправь код постера в лобби на новую страницу» или «сколько сканирований было у флаера на прошлой неделе, по странам?». Помощник получает те же инструменты, что предлагает этот API, по тем же правилам, и коды попадают в ваш дашборд с mcp как источником.
Не разработчик? Простая версия с точными кликами для каждого помощника — на странице Создавайте QR-коды с вашим ИИ-ассистентом.
Подключение
Customize › Connectors › Add custom connector › вставьте адрес или нажмите Connect в листинге QRFLOW. Claude открывает вход в QRFLOW; нажмите Allow. Работает на любом тарифе.
https://qrflow.codes/mcp
Settings › Security and login › включите Developer mode, затем Settings › Plugins › + › вставьте адрес; войдите, когда попросят. Plus, Pro, Team, Enterprise и Edu.
https://qrflow.codes/mcp
Одна команда, затем /mcp для входа. Добавьте Business-ключ как заголовок, чтобы пропустить вход.
claude mcp add --transport http qrflow https://qrflow.codes/mcp
# or, with a key:
claude mcp add --transport http qrflow https://qrflow.codes/mcp --header "Authorization: Bearer $QRFLOW_KEY"
Cursor, Windsurf, VS Code, любой MCP-клиент
Добавьте HTTP-сервер по URL. OAuth-вход происходит в браузере; или передайте заголовок Authorization с ключом.
{
"mcpServers": {
"qrflow": { "type": "http", "url": "https://qrflow.codes/mcp" }
}
}
Ваш собственный агент (Anthropic или OpenAI SDK)
Направьте MCP-коннектор или инструмент на URL с Business-ключом как bearer; браузерный поток не нужен.
// Anthropic Messages API, MCP connector
mcp_servers: [{ type: "url", url: "https://qrflow.codes/mcp", name: "qrflow", authorization_token: process.env.QRFLOW_KEY }]
Что умеет помощник
| Инструмент | Что делает | Область |
|---|---|---|
| list_code_kinds | Каждый вид кода с его полями и требуемым тарифом. Помощник вызывает это перед созданием чего-то необычного. | profile |
| list_domains | Ваши домены ссылок, домен по умолчанию и их id. | domains:read |
| get_qr_image | PNG, который помощник может показать или сохранить, плюс SVG URL для печати. | codes:read |
| get_account | Кто вошел, тариф, лимиты. | profile |
Как это безопасно
- Помощник всегда держит токен только для вашего аккаунта, выданный после того, как вы нажали Allow на странице QRFLOW. Отключите его в любой момент на Account › Connected apps.
- Токены привязаны к MCP-серверу; их нельзя воспроизвести против REST API.
- Каждая запись проходит ту же валидацию, что и дашборд: разрешенные адреса назначения, проверки тарифа, потолки добросовестного использования.
- Деструктивные инструменты описывают себя аккуратно:
delete_qr_codeговорит модели предпочитать паузу, когда существует печать. - Документы обнаружения находятся по адресам
/.well-known/oauth-authorization-serverи/.well-known/oauth-protected-resource; регистрация по RFC 7591; только PKCE S256.
SDK и спецификация OpenAPI
- TypeScript / JavaScript:
npm install qrflow(npm). Ноль зависимостей, ESM и CommonJS, полные типы; работает в Node 18+, Bun, Deno и Workers. Повторяет 429 за вас и поставляетverifyWebhook/parseWebhook. - Python 3.9+, только стандартная библиотека: qrflow.py.
- OpenAPI 3.1: /api/v1/openapi.json. Импортируйте в Postman или Insomnia, сгенерируйте клиент на любом языке или прикрепите к ChatGPT Action.
- Оба клиента выбрасывают типизированную ошибку (
QRFlowErrorсstatus,code,message,retryAfter) и поставляют верификатор вебхуков. Однофайловый TypeScript-исходник все еще находится по адресу /sdk/qrflow.ts, если вы предпочитаете вендорить его.
| TypeScript | Python | Вызовы |
|---|---|---|
| me() | me() | GET /me |
| catalog() | catalog() | GET /catalog |
| listCodes({ limit, q }) | list_codes(limit, q) | GET /codes |
| getCode(id) | get_code(id) | GET /codes/:id |
| createCode(input) | create_code(**fields) | POST /codes |
| updateCode(id, patch) | update_code(id, **patch) | PATCH /codes/:id |
| deleteCode(id) | delete_code(id) | DELETE /codes/:id |
| makeDynamic(id) | make_dynamic(id) | POST /codes/:id/dynamic |
| scans(id, { from, to, group }) | scans(id, from_, to, group) | GET /codes/:id/scans |
| bulkCreate(rows, colors) | bulk_create(rows, **colors) | POST /codes/bulk |
| domains() | domains() | GET /domains |
| listWebhooks() / createWebhook() / testWebhook(id) / deleteWebhook(id) | list_webhooks() / create_webhook() / test_webhook(id) / delete_webhook(id) | /webhooks |
| imageUrl(id, size) | image_url(id, size) | Адрес изображения (получите его с ключом) |
| verifyWebhook(raw, header, secret) | verify_webhook(raw, header, secret) | Проверка подписи для доставок |
Справочник конечных точек
Базовый URL https://qrflow.codes/api/v1. Тела запросов и ответы — в формате JSON. Даты — ISO 8601 в UTC. При PATCH отправляйте только изменяемые поля.
GETprofile
Тарифный план, функциональные флаги и лимиты, действующие для этой учётной записи, а также области действия ключа.
curl https://qrflow.codes/api/v1/me \
-H "Authorization: Bearer $QRFLOW_KEY"
{ "id": "…", "email": "ops@example.com", "plan": "business", "paid": true,
"features": { "dynamic_codes": true, "custom_domain": true, "link_names": true, "gs1": true, "api_keys": true },
"limits": { "saved_codes": 25000, "bulk_per_month": 10000, "bulk_per_request": 2000, "link_domains": 5, "requests_per_minute": 600 },
"auth": "api_key", "scopes": ["codes:read", "codes:write"] }
GETpublic
Встроенные типы (url, wifi, vcard, email, phone, sms, text, location) и около 50 подтипов (Instagram, отзывы Google, Wi-Fi, магазин приложений и т. д.), каждый со своими полями и требуемым тарифным планом. Ключ не требуется.
curl https://qrflow.codes/api/v1/catalog
GETcodes:read
Сначала новые.?limit= до 100,?q= ищет по меткам.
curl "https://qrflow.codes/api/v1/codes?limit=20&q=menu" \
-H "Authorization: Bearer $QRFLOW_KEY"
POSTcodes:write
Те же правила, что и при сохранении на сайте: коды url, phone, email, sms и location являются динамическими на платных тарифах; Wi-Fi, vCard и text содержат своё содержимое в шаблоне. Укажите идентификатор подтипа в destination_data.subtype, чтобы создать, например, код отзыва Google. Необязательный domain_id выбирает, с каким из ваших доменов ссылок будет печататься код (GET /domains выводит их список).
curl -X POST https://qrflow.codes/api/v1/codes \
-H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" \
-d '{ "type": "url", "destination_data": { "url": "https://example.com/menu" }, "label": "Table tents", "frame_style": "caption-below", "frame_caption": "Scan for menu" }'
{ "code": { "id": "…", "label": "Table tents", "kind": "url", "dynamic": true, "short_code": "x7k2p9a",
"short_url": "https://go.example.com/x7k2p9a", "scans": 0, "image_url": "https://qrflow.codes/api/v1/codes/…/image.svg", … } }
GETcodes:read
Код с количеством сканирований, короткой ссылкой и адресом изображения.
curl https://qrflow.codes/api/v1/codes/$ID \
-H "Authorization: Bearer $QRFLOW_KEY"
PATCHcodes:write
Любые из: destination_data (только для динамических кодов, печать остаётся действительной), label, paused, expires_at (ISO или null), slug (имя ссылки на вашем домене), domain_id (с каким из ваших доменов ссылок печатается этот код; null = домен по умолчанию для учётной записи), fg_color, bg_color, frame_style, frame_caption, frame_caption2. Отправляйте только изменяемые поля.
curl -X PATCH https://qrflow.codes/api/v1/codes/$ID \
-H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" \
-d '{ "destination_data": { "url": "https://example.com/menu-fall" }, "slug": "menu" }'
DELETEcodes:write
Удаляется навсегда, включая историю сканирований. Печатная ссылка динамического кода перестаёт открываться. Предпочтительнее использовать paused: true, если печать всё ещё используется.
curl -X DELETE https://qrflow.codes/api/v1/codes/$ID \
-H "Authorization: Bearer $QRFLOW_KEY"
204 No Content
POSTcodes:write
Печатный шаблон меняется (теперь он кодирует короткую ссылку), поэтому после этого необходимо заново отрисовать изображение.
curl -X POST https://qrflow.codes/api/v1/codes/$ID/dynamic \
-H "Authorization: Bearer $QRFLOW_KEY"
GETcodes:read
Готовый к печати SVG с рамкой и цветами.?size= задаёт ширину сетки модулей в пикселях; файл в любом случае масштабируется без потерь.
curl https://qrflow.codes/api/v1/codes/$ID/image.svg \
-H "Authorization: Bearer $QRFLOW_KEY" -o code.svg
GETanalytics:read
?from= и?to= (даты в ISO, до 92 дней, по умолчанию последние 30) и?group= day, device, country, city, browser, os или referrer. Те же цифры, что и на странице аналитики.
curl "https://qrflow.codes/api/v1/codes/$ID/scans?from=2026-09-01&to=2026-09-21&group=day" \
-H "Authorization: Bearer $QRFLOW_KEY"
{ "code_id": "…", "from": "…", "to": "…", "group": "day", "total": 412,
"rows": [ { "key": "2026-09-01", "scans": 18 }, { "key": "2026-09-02", "scans": 25 }, … ] }
POSTcodes:write
До 2 000 URL-кодов за один вызов, все динамические. Учитывается в той же ежемесячной квоте массовых операций, что и страница Bulk (10 000 на тарифе Business). Строки, не являющиеся веб-адресами, возвращаются в rejected; остальные создаются.
curl -X POST https://qrflow.codes/api/v1/codes/bulk \
-H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" \
-d '{ "rows": [ { "destination": "https://example.com/t/1", "label": "Table 1" }, { "destination": "https://example.com/t/2", "label": "Table 2" } ] }'
{ "codes": [ … ], "rejected": [], "remaining_this_month": 9998 }
GETdomains:read
Ваши подключённые домены, их статус и домен, с которым динамические коды печатаются по умолчанию (default_base). Передайте идентификатор домена как domain_id в коде, чтобы напечатать этот код с другим доменом.
curl https://qrflow.codes/api/v1/domains \
-H "Authorization: Bearer $QRFLOW_KEY"
GETwebhooks:manage
Ваши вебхуки с их событиями, последним статусом и количеством сбоев.
curl https://qrflow.codes/api/v1/webhooks \
-H "Authorization: Bearer $QRFLOW_KEY"
POSTwebhooks:manage
url должен быть https на публичном хосте; events — любое из scan, code.created, code.updated, code.deleted. Секрет подписи возвращается один раз.
curl -X POST https://qrflow.codes/api/v1/webhooks \
-H "Authorization: Bearer $QRFLOW_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/hooks/qrflow", "events": ["scan", "code.updated"] }'
{ "webhook": { "id": "…", "url": "…", "events": ["scan", "code.updated"], "active": true, "secret": "whsec_…" } }
POSTwebhooks:manage
Отправляет подписанный ping сейчас и сообщает ответ.
curl -X POST https://qrflow.codes/api/v1/webhooks/$WEBHOOK_ID \
-H "Authorization: Bearer $QRFLOW_KEY"
DELETEwebhooks:manage
Прекращает все доставки, включая поставленные в очередь повторные попытки.
curl -X DELETE https://qrflow.codes/api/v1/webhooks/$WEBHOOK_ID \
-H "Authorization: Bearer $QRFLOW_KEY"
204 No Content
GETpublic
Идентификаторы рамок и что каждой из них требуется (подпись, вторая строка), сгруппированы как в настройщике. Ключ не требуется.
curl https://qrflow.codes/api/v1/frames
Объект Code
Каждая конечная точка, работающая с кодом, возвращает одну и ту же структуру. Игнорируйте неизвестные поля; со временем добавляются новые.
| Поле | Тип | Значение |
|---|---|---|
| id | uuid | Стабильный идентификатор. Используйте его во всех остальных вызовах. |
| label | string | null | Имя на панели управления. До 120 символов. Можно искать с помощью?q=. |
| kind | string | Идентификатор каталога: url, wifi, instagram, googlereview,... kind_label — человекочитаемое имя. |
| type | string | Кодировка: url, text, wifi, vcard, email, phone, sms, location. |
| destination_data | object | Отправленные вами поля (плюс subtype для видов). destination — однострочное резюме. |
| dynamic | boolean | True, когда сканирования проходят через QRFLOW и назначение может меняться. dynamic_capable показывает, может ли этот тип быть динамическим на платном тарифе. |
| short_code | string | Семь символов, никогда не меняется. |
| short_url | string | Что печатать для динамического кода. Включает ваш домен и slug, если заданы. |
| domain_id | uuid | null | С каким доменом ссылок печатается этот код; null означает домен по умолчанию для учётной записи. |
| fg_color, bg_color | hex | Цвета модуля и фона. |
| has_logo | boolean | Логотип был добавлен на панели управления; image.svg включает его. |
| frame_style, frame_caption, frame_caption2 | string | null | Идентификатор рамки и подписи, как в настройщике. |
| scans | integer | Общее количество сканирований за всё время. |
| created_at, updated_at | ISO 8601 | UTC. |
| manage_url | url | Страница кода на панели управления, для ссылки «Открыть в QRFLOW». |
| image_url | url | GET /codes/:id/image.svg. Требуется заголовок Authorization; это не публичный URL изображения. |
| svg_download_url, png_download_url | url | Тот же SVG (рамка, цвета, логотип) и обычный PNG по подписанным ссылкам, действующим 24 часа без заголовка: для тегов <img>, скриптов и ассистентов, сохраняющих файл. download_expires_at показывает, когда они истекают; любое чтение кода возвращает свежие ссылки. |
Другие структуры: Scans (code_id, from, to, group, total, rows[key, scans]), Domain (id, host, status, active, is_default, verified_at, grace_until), Webhook (id, url, events, active, last_status, last_delivery_at, consecutive_failures, плюс secret один раз), Me (id, email, plan, paid, features, limits, auth, scopes) и Error (error, message). В документе OpenAPI указаны типы всех свойств.
Business
Вебхуки
QRFLOW вызывает ваш https-URL, когда что-то происходит. Создайте его на Account › Webhooks или с помощью POST /webhooks; секрет подписи вы получаете один раз. До 10 на учётную запись.
| Событие | Когда | data |
|---|---|---|
| scan | Пакетно: каждые несколько минут все новые сканирования с момента последней доставки, до 500 за вызов. | count, from, to, scans[] с code_id, label, short_code, slug, scanned_at, device, country, city, referrer, browser, os, language |
| code.created | Немедленно из API и ассистентов; в течение нескольких минут с панели управления. Массовый запрос отправляет одно событие с bulk: true и codes[]. | code, source |
| code.updated | Та же периодичность. Охватывает назначение, метку, паузу, срок действия, имя ссылки, домен, цвета, рамку и преобразование в динамический. | code, changed[] (имена изменённых полей) |
| code.deleted | Та же периодичность. | code: { id, label, short_code, slug } |
| ping | Когда вы нажимаете Test. | webhook_id, message |
Что приходит
Каждая полезная нагрузка — это { id, event, created_at, data }. id стабилен при повторных попытках одной доставки, поэтому вы можете дедуплицировать по нему.
{
"id": "9b1c6d2e-…",
"event": "scan",
"created_at": "2026-09-21T18:05:00.000Z",
"data": {
"count": 2,
"from": "2026-09-21T18:00:00.000Z",
"to": "2026-09-21T18:04:12.331Z",
"scans": [
{ "code_id": "…", "label": "Table tents", "short_code": "x7k2p9a", "slug": "menu", "scanned_at": "2026-09-21T18:03:40.101Z",
"device": "mobile", "country": "US", "city": "Las Vegas", "referrer": null, "browser": "Safari", "os": "iOS", "language": "en-US" },
{ "code_id": "…", "label": "Table tents", "short_code": "x7k2p9a", "slug": "menu", "scanned_at": "2026-09-21T18:04:12.331Z",
"device": "mobile", "country": "MX", "city": "Tijuana", "referrer": null, "browser": "Chrome", "os": "Android", "language": "es-MX" }
]
}
}
{
"id": "2f0a…",
"event": "code.updated",
"created_at": "2026-09-21T18:06:00.000Z",
"data": {
"code": { "id": "…", "label": "Table tents", "kind": "url", "dynamic": true, "short_url": "https://go.example.com/menu", "scans": 412, "…": "…" },
"changed": ["destination_data"]
}
}
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: QRFLOW-Webhooks/1.0 (+https://qrflow.codes/developers)
X-QRFLOW-Event: scan
X-QRFLOW-Signature: t=1758477900,v1=5f1c…e9
Проверка подписи
X-QRFLOW-Signature: t=<unix seconds>,v1=<hex>. Вычислите HMAC-SHA256 от ${t}.${rawBody} с вашим секретом и сравните с v1 за постоянное время; отклоняйте, если t старше пяти минут. Используйте полученные необработанные байты, никогда не повторно сериализованный объект. Рабочие приёмники для Next.js и Python есть в рецептах, и оба SDK включают вспомогательную функцию.
Правила доставки
- Ответьте любым 2xx в течение 8 секунд. Выполняйте работу после ответа.
- Всё остальное повторяется через 1, 5, 15, 60, 240 и 720 минут.
- Двадцать последовательных сбоев отключают вебхук и отправляют письмо владельцу учётной записи. Включите его снова, когда приёмник исправлен; поставленные в очередь повторные попытки возобновятся.
- URL должны быть https на публичном хосте. localhost, частные диапазоны и сам qrflow.codes отклоняются. Используйте туннель во время разработки.
- Нажмите Test, чтобы получить подписанный
pingи увидеть статус, которым ответил ваш сервер.
Ошибки
Каждая ошибка — это { "error": "<code>", "message": "<what to do>" } со статусом ниже. Сообщение написано для человека; покажите его.
| Статус | error | Значение |
|---|
Симптом, причина, решение
Устранение неполадок
401 invalid_token при каждом вызове
ПочемуЗаголовок неверный или ключ не активен.
РешениеОтправьте точно Authorization: Bearer qrf_live_… (пробел, а не двоеточие). Проверьте, что ключ не был отозван в Account › API keys. Если вы скопировали его из чата или документа, обратите внимание на завершающую точку или типографскую кавычку.
401 на /api/v1 с токеном, который работает на MCP-сервере
ПочемуТокены, выпущенные для https://qrflow.codes/mcp, привязаны к нему.
РешениеИспользуйте API-ключ для REST или запустите второй OAuth-поток без resource=, чтобы получить токен для REST API.
402 upgrade_required при создании ключа или вебхука
ПочемуОбе функции доступны на тарифе Business.
РешениеОбновите тариф на /pricing или используйте MCP-сервер, который работает на любом плане через вход в систему.
402 на POST /codes из OAuth-приложения
ПочемуТарифный план пользователя не включает то, что запросило приложение (динамический код, домен).
РешениеСначала прочитайте GET /me features и адаптируйтесь: создайте код в любом случае (на Free он будет статическим) или сообщите пользователю, что требуется для тарифа.
403 insufficient_scope
ПочемуОбласти действия фиксируются при создании ключа.
РешениеСоздайте новый ключ с нужными областями и отзовите старый. Для OAuth запросите область в authorize-запросе.
400 not_dynamic при PATCH destination_data
ПочемуКод статический: создан на Free или имеет тип Wi-Fi/vCard/text.
РешениеДля url/phone/email/sms/location на платном тарифе выполните POST /codes/:id/dynamic, затем заново скачайте и распечатайте (изображение меняется). Wi-Fi, vCard и text никогда не могут быть динамическими; вместо этого создайте url-код, открывающий страницу.
400 no_domain при установке slug
ПочемуИмена ссылок живут на вашем домене.
РешениеСначала подключите и подтвердите домен на странице Account. На qrflow.codes/q путь всегда равен short_code.
409 conflict на slug
ПочемуДругой ваш код уже использует это имя.
РешениеВыполните GET /codes?q=, чтобы найти его, или выберите другое имя. Имена уникальны для учётной записи, а не глобально.
Ошибка CORS в консоли браузера
ПочемуAPI принимает только вызовы сервер-к-серверу (и Canva). Это намеренно: ключ на веб-странице — это утёкший ключ.
РешениеПеренесите вызов в обработчик маршрута, серверное действие, edge-функцию или бэкенд и вызывайте его со страницы.
На изображении водяной знак QRFLOW
ПочемуУчётная запись на тарифе Free.
РешениеПлатные тарифы убирают его. Free предназначен для собственного генератора сайта.
short_url всё ещё показывает qrflow.codes/q/… после добавления моего домена
ПочемуДомен ещё не подтверждён или его CNAME неверен.
РешениеПроверьте статус на странице Account или через GET /domains (статус должен быть verified). Существующие коды переключатся автоматически после подтверждения.
image_url даёт 401 в теге <img>
ПочемуТребуется заголовок Authorization, который тег <img> отправить не может.
РешениеИспользуйте svg_download_url или png_download_url из того же объекта Code: подписанные ссылки, действующие 24 часа без заголовка. Для постоянного доступа проксируйте image_url через свой сервер (см. рецепт Next.js) или закодируйте short_url самостоятельно.
Мне нужен PNG, а не SVG
ПочемуSVG содержит рамку и логотип; PNG — это обычный код.
РешениеGET /codes/:id/image.png (bearer или подписанный png_download_url) возвращает PNG размером от 256 до 2048 px. Для PNG с рамкой конвертируйте SVG с помощью sharp или resvg (sharp(svgBuffer).png().toBuffer()).
Мой ассистент сказал, что конечная точка изображения отказала ему, и нарисовал код сам
ПочемуОн запросил image_url, который требует bearer.
РешениеКаждый код теперь содержит png_download_url и svg_download_url, и get_qr_image возвращает их; ассистент может скачать их без входа. Локально нарисованный код, кодирующий тот же short_url, по-прежнему работает и учитывает сканирования, но у него нет рамки и логотипа.
Вебхук никогда не приходит
ПочемуПравила URL или приёмник.
РешениеURL должен быть https на публичном хосте (без localhost, без частных IP, не qrflow.codes). Нажмите Test на вебхуке: результат покажет статус, которым ответил ваш сервер. События scan группируются и могут занимать до пяти минут; события code.* с панели управления также ставятся в очередь на несколько минут, тогда как записи из API и MCP доставляются сразу.
Подпись никогда не проверяется
ПочемуВы подписали повторно сериализованное тело.
FixVerify выполняется по точным исходным байтам, которые вы получили, до разбора JSON. В Express используйте express.raw({ type: 'application/json' }) на этом маршруте; в Next.js App Router используйте await req.text(); в Flask request.get_data(). Затем вычислите HMAC-SHA256 от ${t}.${raw}\.
Вебхук сам отключился
ПочемуДвадцать последовательных сбоев.
ИсправлениеИсправьте получатель, затем снова активируйте его (Аккаунт › Вебхуки, или удалите и создайте заново). Вам было отправлено письмо, когда это произошло. Поставленные в очередь повторные попытки возобновятся.
Дублирующиеся доставки вебхуков
ПочемуМедленный ответ 2xx (более 8 секунд) считается сбоем и повторяется.
ИсправлениеСначала отвечайте, потом обрабатывайте. Дедуплицируйте по id в полезной нагрузке, который стабилен при повторных попытках.
429 rate_limited во время импорта
Почему600 запросов в минуту на ключ.
ИсправлениеИспользуйте POST /codes/bulk (2 000 кодов в одном запросе) вместо одного POST на код, или подождите Retry-After секунд.
Я удалил код, и напечатанный постер теперь показывает «Код не найден»
ПочемуУдаление необратимо и разрывает ссылку.
ИсправлениеОтмены нет. В следующий раз используйте PATCH { paused: true }; приостановленный код показывает дружелюбную страницу и может быть возобновлён.
Мой ключ перестал работать после понижения тарифа
ПочемуКлючи продолжают работать 30 дней после ухода с Business, затем отвечают 402.
ИсправлениеОформите подписку заново; ничего не было удалено, и те же ключи снова работают.
Что-то не из списка? hello@qrflow.codes, с точным запросом и JSON-ошибкой, которую вы получили. Аккаунты Business получают приоритет.
Лимиты и добросовестное использование
| Лимит | |
|---|---|
| Запросов в минуту на ключ | 600. 429 с Retry-After сверх этого. |
| Ключей на аккаунт | 10 |
| Вебхуков на аккаунт | 10 |
| Сохранённых кодов (добросовестное использование) | 1 000 Premium, 25 000 Business; API останавливается на удвоенном значении. |
| Массовые операции | 500/месяц (500 за запрос) Premium; 10 000/месяц (2 000 за запрос) Business. |
| Домены ссылок | 1 Premium, 5 Business |
| Сканирования | Без ограничений. Контрольное письмо при 100 000 сканированиях на код в месяц на Premium, 1 000 000 на Business; ничего не ограничивается. |
| Окно аналитики сканирований | 92 дня на запрос |
| Размер страницы списка | 100 (?limit=) |
| Метка / подписи / слаг | 120 / 60 / 40 символов |
| Таймаут и повторные попытки вебхука | 8 секунд; повторные попытки через 1, 5, 15, 60, 240 и 720 минут; отключение после 20 последовательных сбоев. |
| После ухода с Business | Ключи и вебхуки продолжают работать 30 дней, затем 402. Ничего не удаляется. |
Добросовестное использование — это то, на что рассчитан тариф. Ничего не ограничивается на этом числе; API останавливается на удвоенном значении, и вам сначала пишет человек. Более высокие объёмы: hello@qrflow.codes.
Безопасность — для вас и для тех, кто сканирует
Как QRFLOW защищает ваш аккаунт
- Ключи показываются один раз и хранятся как SHA-256 хеши. Никто в QRFLOW не может прочитать ключ обратно; если вы его потеряли, создайте новый.
- Каждый запрос ограничен аккаунтом, которому принадлежит ключ. id кода из другого аккаунта — это 404, никогда не утечка.
- Области действия фиксированы для каждого ключа, поэтому ключ для панели отчётности не может создавать или удалять коды.
- 600 запросов в минуту на ключ; сверх этого — чистый 429, а не замедление для всех.
- Назначения находятся в белом списке: http, https, mailto, tel, sms, geo и короткий список схем приложений (whatsapp, tg, signal, spotify, магазины приложений). javascript:, data: и file: отклоняются при создании, поэтому скомпрометированная интеграция не может превратить ваши коды в атаку.
- URL вебхуков должны быть https на публичных хостах; QRFLOW никогда не вызывает частные сети или сам себя. Каждая доставка подписана, и каждая полезная нагрузка имеет стабильный id.
- OAuth-клиенты регистрируются с PKCE S256, и токены привязаны к серверу, для которого они выданы; токен для MCP-сервера не может быть воспроизведён на REST API.
- Любой может отозвать ключ или отключить приложение на странице Аккаунта; эффект немедленный.
Что делать с вашей стороны
- Переменные окружения, никогда исходный код. Если ключ попал в историю git, отзовите его.
- Только на стороне сервера. API отклоняет браузерные источники, но ваши собственные конечные точки, которые его оборачивают, тоже нуждаются в аутентификации, иначе любой может создавать коды за ваш счёт.
- Дайте каждой интеграции свой ключ с нужными областями действия, названный по интеграции. Отзыв одного тогда влияет на одну вещь.
- Проверяйте подписи вебхуков и отклоняйте метки времени старше пяти минут.
- Если данные ваших пользователей попадают в метки или назначения, помните, что QRFLOW их хранит; по возможности держите личные данные вне меток.
Что записывают сканирования, а что нет
- Каждое перенаправление хранит тип устройства, страну, город, реферер, браузер, операционную систему и язык, полученные из запроса, и односторонний хеш кода + дня + IP + пользовательского агента, чтобы владелец мог подсчитать уникальных посетителей. Хеш нельзя превратить обратно в адрес.
- На сканирующего человека не устанавливаются файлы cookie, и сам IP-адрес не хранится со сканированием. Известные боты и краулеры предпросмотра ссылок пропускаются.
- Удаление кода удаляет его сканирования. Удаление аккаунта удаляет всё.
- Полный текст: https://qrflow.codes/privacy и https://qrflow.codes/terms.
Версионирование и стабильность
API версионируется в пути: /api/v1. В рамках v1 мы добавляем поля, конечные точки, виды и события; мы ничего не удаляем и не переименовываем, и неизвестные поля в ответах должны игнорироваться вашим кодом.
Если изменение когда-либо должно сломать v1, оно выходит как /api/v2, и v1 продолжает работать как минимум двенадцать месяцев. Владельцам ключей отправляется письмо о прекращении поддержки за 90 дней.
MCP-сервер следует тому же правилу для своих инструментов: аргументы только добавляются, и каждый инструмент сохраняет своё имя.
Документ OpenAPI по адресу /api/v1/openapi.json и Markdown по адресу /llms-full.txt генерируются из кода, который обслуживает API, поэтому они описывают то, что работает сегодня.
Вопросы разработчиков
Нужно ли платить за использование QRFLOW API?
Ключи API входят в план Business, $29 в месяц, помесячно. MCP-сервер (Claude, ChatGPT, Cursor, Claude Code) и OAuth для вашего собственного приложения работают на каждом плане через вход в систему, и то, что они могут создавать, следует плану. GET /catalog, GET /frames и /preview.svg не требуют ключа вообще.
Могу ли я бесплатно генерировать QR-коды через API?
Не с ключом. Для простого статического изображения бесплатный генератор на qrflow.codes или любая библиотека QR с открытым исходным кодом справится. API предназначен для динамических кодов, вашего собственного домена, аналитики, массовых операций и вебхуков — это то, для чего нужен платный аккаунт.
Могу ли я вызывать API из браузера?
Нет. Он отклоняет браузерные источники, чтобы ключ никогда не попал на веб-страницу. Вызывайте его из обработчика маршрута, серверного действия, edge-функции или бэкенда, и вызывайте это со своей страницы.
Какие форматы изображений я получаю?
SVG с вашими цветами, рамкой, подписями и логотипом (GET /codes/:id/image.svg, номинально от 256 до 4096 px) и обычный PNG (GET /codes/:id/image.png, от 256 до 2048 px). Оба принимают bearer или подписанные svg_download_url / png_download_url, которые несёт каждый объект Code и которые работают 24 часа без заголовка. Инструмент MCP get_qr_image возвращает PNG встроенно плюс обе ссылки.
Могу ли я изменить QR-код после печати?
Да, если он динамический (url, phone, email, sms, location на платном плане). PATCH /codes/:id с новым destination_data; картинка не меняется, следующее сканирование ведёт в новое место. Wi-Fi, vCard и текстовые коды несут своё содержимое в картинке и не могут быть изменены.
В чём разница между short_url и назначением?
short_url — это ссылка внутри картинки (go.example.com/menu). Назначение — это то, куда эта ссылка перенаправляет (https://example.com/menu-fall). Вы печатаете short_url один раз и меняете назначение сколько угодно.
Могут ли коды использовать мой собственный домен?
Да. Premium подключает 1 домен, Business 5; вы добавляете CNAME и подтверждаете на странице Аккаунта. Business выбирает домен для каждого кода с domain_id. Имена ссылок (слаг) создают читаемые пути на нём.
Что записывает сканирование о сканирующем человеке?
Тип устройства, страну, город, реферер, браузер, операционную систему и язык из запроса, плюс односторонний ежедневный хеш для подсчёта уникальных посетителей. Без файлов cookie, и IP-адрес не хранится. Достаточно для графика, недостаточно для идентификации кого-либо. Подробности: https://qrflow.codes/privacy#scans
Есть ли пакет npm или PyPI?
npm: npm install qrflow\ (https://www.npmjs.com/package/qrflow), без зависимостей, ESM и CommonJS, полные типы TypeScript, работает в Node 18+, Bun, Deno и Workers; он оборачивает каждую конечную точку, повторяет 429 и включает verifyWebhook/parseWebhook. Python: однофайловый клиент по адресу https://qrflow.codes/sdk/qrflow.py (только стандартная библиотека) с verify_webhook; пакет PyPI последует.
Работает ли это с Claude, ChatGPT, Cursor и Claude Code?
Да. QRFLOW — это MCP-сервер по адресу https://qrflow.codes/mcp. Добавьте его как коннектор, войдите один раз и спрашивайте простыми словами. Одиннадцать инструментов покрывают создание, редактирование, приостановку, именование, массовые операции, аналитику, изображения и домены.
Могут ли мои пользователи подключать свои аккаунты QRFLOW к моему приложению?
Да, с OAuth 2.0. Зарегистрируйте клиент по адресу /api/oauth/register (аккаунт не нужен), отправляйте пользователей на /oauth/authorize с PKCE и вызывайте API с их токеном. Коды попадают в их аккаунт под их планом.
Как мне тестировать вебхуки на localhost?
Откройте ваш dev-сервер через туннель (cloudflared или ngrok) и используйте его https-адрес как URL вебхука, затем нажмите Тест на Аккаунт › Вебхуки, чтобы получить подписанный ping. URL вебхуков должны быть публичными https; localhost и частные адреса отклоняются.
Что произойдёт с моей интеграцией, если я отменю Business?
Ключи и вебхуки продолжают работать 30 дней, затем отвечают 402. Коды, сканирования и домены остаются в аккаунте. Повторная подписка включает всё обратно с теми же ключами.
Как мне сделать код Google review, Instagram, Wi-Fi или PDF через API?
GET /catalog перечисляет каждый вид с его полями. Затем POST /codes с типом и полями вида, добавляя subtype для видов: { type: 'url', destination_data: { subtype: 'googlereview', placeId: 'ChIJ…' } }, { type: 'wifi', destination_data: { ssid, password, encryption: 'WPA' } }, { type: 'url', destination_data: { subtype: 'instagram', handle: 'acme' } }.
Может ли API загрузить логотип на код?
Пока нет. Добавьте логотип в панели управления; image.svg включает его, и has_logo сообщает вам, что он там. Цвета, рамки и подписи настраиваются через API.
Стабилен ли API?
v1 только добавляет; он никогда не удаляет и не переименовывает. Ломающее изменение вышло бы как v2 с сохранением v1 как минимум двенадцать месяцев и уведомлением по электронной почте за 90 дней.
Для агентов, инструментов и ассистентов, читающих это
Машиночитаемое
Всё на этой странице существует в форме, которую программное обеспечение может получить. Всё это генерируется из кода, который обслуживает API, поэтому оно никогда не устаревает.
| URL | Что это | |
|---|---|---|
| llms-full.txt | https://qrflow.codes/llms-full.txt | Весь этот справочник в формате Markdown: концепции, каждая конечная точка, каждый MCP-инструмент, рецепты, устранение неполадок, FAQ. Сгенерировано из того же источника, что и эта страница. |
| developers.md | https://qrflow.codes/developers.md | Тот же документ, для инструментов, которые загружают .md. |
| llms.txt | https://qrflow.codes/llms.txt | Индекс сайта для ассистентов, указывающий сюда. |
| API на одной странице | https://qrflow.codes/qr-code-api | Что делает API, когда клиентская библиотека — лучшее решение, и сколько это стоит. Краткая версия этого справочника для принятия решения, а не для разработки. |
| openapi.json | https://qrflow.codes/api/v1/openapi.json | OpenAPI 3.1. Импортируйте в Postman, Insomnia, генератор кода или ChatGPT Action. |
| MCP-сервер | https://qrflow.codes/mcp | Streamable HTTP, OAuth с динамической регистрацией или Business-ключом в качестве bearer. |
| server.json | https://qrflow.codes/.well-known/mcp/server.json | Манифест реестра MCP. |
| OAuth discovery | https://qrflow.codes/.well-known/oauth-authorization-server | Метаданные RFC 8414; документ защищённого ресурса находится рядом. |
| npm-пакет | https://www.npmjs.com/package/qrflow | npm install qrflow. Типизированный клиент, ноль зависимостей, проверка вебхуков. Python-клиент в одном файле на https://qrflow.codes/sdk/qrflow.py. |
| GitHub | https://github.com/nativecodeapps/qrflow-sdk | Клиенты, снимок OpenAPI и запускаемые примеры для вебхуков Next.js, Workers, Express, FastAPI и Flask. Приветствуются вопросы и PR. |
Вопросы, идеи, вид кода, который нам стоит добавить: hello@qrflow.codes. Условия: /terms. Конфиденциальность: /privacy.