QRFLOW.codes

offiziell

QR-Codes erstellen, gedruckte dynamische Codes neu ausrichten, Links auf der eigenen Domain benennen und Scan-Analysen lesen.

Was kann man mit QRFLOW Codes MCP machen?

  • Dynamische QR-Codes erstellen — Fordern Sie an, einen druckbaren short_url für jede URL zu generieren, wobei das Ziel jederzeit nach dem Drucken geändert werden kann.
  • Gedruckte Codes umleiten — Fordern Sie an, das destination_data eines Codes auf eine neue URL zu aktualisieren; bereits gedruckte Codes funktionieren weiterhin ohne Neudruck.
  • Scan-Analysen abrufen — Fragen Sie nach Scans-Aufschlüsselungen nach Tag, Land oder Gerät, um zu sehen, wie ein gedruckter Code abschneidet.
  • Codes pausieren oder ablaufen lassen — Weisen Sie an, einen Code zu pausieren oder ein Ablaufdatum festzulegen, wenn eine Kampagne oder ein Angebot endet.
  • Links auf Ihrer Domain benennen — Fordern Sie an, einen lesbaren slug auf Ihrer eigenen Domain festzulegen, sodass Codes als go.yourbrand.com/menu gedruckt werden, statt als zufälliger Pfad.

Gehosteter MCP-Server

npx add-mcp 'https://qrflow.codes/mcp'

Installiert in Claude Code, Codex, Cursor und mehr

Dokumentation

QRFLOW.codes für Entwickler

Hier starten

QRFLOW.codes erstellt QR-Codes, die Sie nach dem Drucken ändern können, auf Ihrer eigenen Domain, mit Scan-Analysen, und lässt Ihre Software und Ihren KI-Assistenten alles über eine einzige API erledigen.

Ein QR-Code ist ein Bild einer Zeichenkette. Die meisten Generatoren setzen Ihre Webadresse in das Bild; wenn sich die Adresse ändert, ist der Druck wertlos. QRFLOW setzt einen kurzen Link in das Bild (go.yourbrand.com/menu oder qrflow.codes/q/x7k2p9a) und leitet ihn weiter. Sie ändern das Ziel, wann immer Sie möchten, und jeder Scan wird gezählt. Das ist ein dynamischer Code, und das ist die Sache, die eine API wert ist.

Die API macht genau das, was das Dashboard tut: Codes jeder Art erstellen, sie neu ausrichten, ihre Links benennen, auswählen, auf welcher Ihrer Domains sie gedruckt werden, Scan-Zahlen abrufen, Tausende auf einmal erstellen und benachrichtigt werden, wenn etwas passiert (Webhooks). Dieselben Werkzeuge sind als MCP-Server verfügbar, sodass Claude, ChatGPT, Cursor und Claude Code Ihr Konto in einfachen Worten steuern können.

Zugriff: Die REST-API akzeptiert einen Business-API-Schlüssel (29 $ pro Monat, erstellt auf der Kontoseite) oder ein OAuth-Token. Der MCP-Server funktioniert auf jedem Plan über die OAuth-Anmeldung; was der Assistent erstellen darf, folgt dem Plan wie überall sonst.

Ob Sie es überhaupt nutzen sollten? Die QR-Code-API-Seite ist die Kurzversion: was sie tut, was eine clientseitige Bibliothek besser macht und was sie kostet.

Wenn Sie ein KI-Assistent sind, der jemandem beim Aufbau mit QRFLOW hilft

Willkommen. Diese Seite ist genauso für Sie geschrieben wie für die Person, der Sie helfen. So sieht gute Hilfe aus:

  1. Konto bestätigen: API-Schlüssel benötigen den Business-Plan. Wenn sie keinen haben, verweisen Sie sie auf https://qrflow.codes/pricing und Konto › API-Schlüssel; erfinden Sie keinen Schlüssel oder einen kostenlosen Tarif, der nicht existiert.
  2. Bewahren Sie den Schlüssel auf dem Server auf. Lesen Sie ihn aus einer Umgebungsvariable (QRFLOW_KEY) in einem Routen-Handler, einer Server-Action, einer Edge-Funktion oder einem Backend. Die API lehnt Browser-Ursprünge absichtlich ab (CORS), daher kann reiner Frontend-Code sie nicht aufrufen.
  3. Erstellen Sie dynamische Codes mit Typ "url" und destination_data.url. Speichern Sie die zurückgegebene id und short_url in ihrer Datenbank. Drucken oder zeigen Sie short_url an; das Ziel kann später mit PATCH /codes/:id geändert werden und der Druck bleibt gültig.
  4. Zum Anzeigen oder Speichern des Bildes: Jedes Code-Objekt hat png_download_url und svg_download_url, signierte Links, die 24 Stunden ohne Header funktionieren (gut für einen einmaligen Speichervorgang oder eine Vorschau). Für etwas Dauerhaftes in ihrer App, proxyen Sie GET /codes/:id/image.svg über ihren Server mit dem Schlüssel, oder kodieren Sie short_url mit einer beliebigen QR-Bibliothek auf dem Client; das Tracking funktioniert trotzdem, weil der Link durch QRFLOW läuft.
  5. Senden Sie nur die Felder, die sich bei PATCH ändern. Ändern Sie niemals slug oder domain_id, nachdem etwas gedruckt wurde; beide ändern den gedruckten Link.
  6. Bevorzugen Sie paused: true gegenüber DELETE, wenn ein Druck existiert. Löschen tötet den Link.
  7. Für Ereignisse verwenden Sie Webhooks (Konto › Webhooks oder POST /webhooks) und verifizieren Sie den X-QRFLOW-Signature-Header mit dem rohen Anfrage-Body. Pollen Sie GET /codes nicht in einer Schleife.
  8. Wenn sie QRFLOW aus ihrem Chat statt aus Code verwenden möchten, verbinden Sie den MCP-Server unter https://qrflow.codes/mcp;; dafür ist kein Schlüssel nötig.
  9. Wenn etwas fehlschlägt, lesen Sie error und message im JSON-Body. Der Abschnitt zur Fehlerbehebung unten ordnet jedem Fehlercode eine Lösung zu.
  10. Die vollständige Referenz in Markdown finden Sie unter https://qrflow.codes/llms-full.txt und das OpenAPI-3.1-Dokument unter https://qrflow.codes/api/v1/openapi.json.. Beide werden aus derselben Quelle wie diese Seite generiert.

Menschen: Dieser Block ist unsere Methode, um sicherzustellen, dass der Assistent, mit dem Sie arbeiten, Ihnen die sichere Version jeder Antwort gibt. Er ist zufällig auch eine gute Zusammenfassung.

Welchen Plan Sie benötigen

Der API-Schlüssel ist das Einzige, das nur für Business verfügbar ist. Alles, was ein Assistent über den MCP-Server tut, und alles, was eine Drittanbieter-App über OAuth tut, funktioniert auf jedem Plan und folgt einfach den Funktionen dieses Plans. Vollständige Preise und faire Nutzung: /pricing.

KostenlosPremium 4 $Business 29 $
API-Schlüssel (REST aus Ihrem Code)NeinNeinJa, bis zu 10 Schlüssel
MCP-Server (Claude, ChatGPT, Cursor, Claude Code)Ja, anmeldenJaJa, anmelden oder Schlüssel
OAuth für Ihre eigene App (Benutzer verbinden ihr QRFLOW)JaJaJa
Dynamische Codes (Ziel nach dem Drucken ändern)Nein, nur statischJaJa
Eigene Link-DomainNein1 Domain5 Domains, pro Code wählbar
Link-Namen (go.brand.com/menu)NeinJaJa
Scan-AnalysenNeinJaJa
WebhooksNeinNeinJa, bis zu 10
MassenerstellungNein500/Monat, 500 pro Anfrage10.000/Monat, 2.000 pro Anfrage
Gespeicherte Codes (faire Nutzung)Eine Handvoll1.00025.000
Team-Sitzplätze115
Preis0 $4 $/Monat29 $/Monat

Zwölf Wörter, die die ganze Arbeit erledigen

Konzepte

Lesen Sie diese einmal, und jeder Endpunkt unten wird Sinn ergeben.

Static code

Der Inhalt ist im Bild. WLAN-, Kontaktkarten- (vCard) und Klartext-Codes sind immer statisch, und auf dem kostenlosen Plan ist jeder Code statisch. Ein statischer Code benötigt keinen Server und läuft nie ab, und er kann nicht geändert oder gezählt werden.

Dynamic code

Das Bild enthält einen kurzen Link, den QRFLOW weiterleitet. url-, Telefon-, E-Mail-, SMS- und Standort-Codes sind auf Premium und Business dynamisch. Sie können sie neu ausrichten, pausieren, ablaufen lassen, umbenennen und zählen, ohne den Druck anzufassen.

short_url

Die genaue Zeichenkette, die in einem dynamischen Code kodiert ist, und die Sache, die gedruckt wird. Sie ist https://qrflow.codes/q/<short_code>, bis Sie eine Domain verbinden, dann https://<your domain>/<slug or short_code>.. Jedes Code-Objekt trägt sie.

short_code

Sieben zufällige Zeichen, eindeutig pro Code, bei der Erstellung zugewiesen und nie geändert. Der Fallback-Pfad, wenn ein Code keinen Link-Namen hat.

slug (link name)

Ein lesbarer Pfad auf Ihrer eigenen Domain: go.example.com/menu. 3 bis 40 Kleinbuchstaben, Ziffern und Bindestriche, eindeutig innerhalb Ihres Kontos, nur mit einer verbundenen Domain. Setzen Sie ihn vor dem Drucken: Eine Änderung ändert den gedruckten Link.

Link domain

Ein Hostname, den Sie besitzen (go.example.com), der per CNAME auf QRFLOW zeigt und auf der Kontoseite verifiziert ist. Premium erhält einen; Business erhält fünf und kann pro Code mit domain_id wählen. Die älteste aktive Domain ist die Standardeinstellung.

Kind, type and subtype

type ist die Kodierung: url, text, wifi, vcard, email, phone, sms, location. Eine Art ist ein freundlicherer Name für das, was Menschen wollen (instagram, googlereview, whatsapp, pdf, menu, appstore,...). Die meisten Arten sind url-Codes mit gesetztem destination_data.subtype. GET /catalog listet jede Art mit ihren Feldern auf; kind auf einem Code sagt Ihnen, welche es ist.

destination_data

Die Felder für den Typ, als Zeichenketten: { url } für eine Website, { ssid, password, encryption } für WLAN, { placeId } für eine Google-Bewertung, { handle } für Instagram. Bei einem dynamischen Code können Sie sie jederzeit ersetzen.

Scans

Jede Weiterleitung zeichnet Gerätetyp, Land, Stadt, Referrer, Browser, Betriebssystem und Sprache aus der Anfrage selbst auf, plus einen Einweg-Tages-Hash zum Zählen eindeutiger Besucher. Es werden keine Cookies gesetzt und die IP-Adresse wird nicht gespeichert. scans auf einem Code ist die Gesamtzahl über die Lebensdauer; GET /codes/:id/scans schlüsselt sie auf.

Source

Jeder Code merkt sich, was ihn erstellt hat: dashboard, api:<key name>, mcp, canva oder bulk. Es wird im Dashboard und in Webhook-Payloads angezeigt, sodass Sie die Codes Ihrer Integration von handgemachten unterscheiden können.

Workspace

Ein Business-Inhaber kann bis zu vier Teammitglieder einladen. Schlüssel und Webhooks gehören zum Konto des Inhabers; Codes, die von jemandem im Arbeitsbereich erstellt wurden, sind für das gesamte Team sichtbar.

Fünf Minuten

Schnellstart

Einen Schlüssel erhalten

  1. Öffnen Sie auf dem Business-Plan Konto › API-Schlüssel.
  2. Benennen Sie ihn nach dem, wofür er ist („Shop-Backend", „Berichterstattung") und wählen Sie seine Bereiche. Bereiche können später nicht geändert werden; erstellen Sie einen neuen Schlüssel, wenn Sie mehr benötigen.
  3. Kopieren Sie ihn einmal. Er sieht aus wie qrf_live_…. Legen Sie ihn in eine Umgebungsvariable namens QRFLOW_KEY.
  4. Senden Sie ihn als Authorization: Bearer $QRFLOW_KEY bei jeder Anfrage. Das ist die gesamte Authentifizierungsgeschichte.

Schlüssel sind für Server. Legen Sie niemals einen in eine Webseite, eine mobile App oder eine gemeinsame Tabelle; widerrufen und erneuern Sie ihn, wenn einer durchsickert.

Dieselben fünf Schritte in curl, TypeScript und Python. Jeder erstellt einen dynamischen Code, lädt sein Bild herunter, ändert sein Ziel und liest seine Scans.

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

Authentifizierung

API-Schlüssel (Business)

Bis zu 10 pro Konto, 600 Anfragen pro Minute jeweils, gehasht gespeichert, einmal angezeigt. Ein Schlüssel trägt die Bereiche, mit denen er erstellt wurde:

BereichErlaubt
profileGET /me: Plan, Funktionen, Grenzen. Jeder Schlüssel hat ihn.
codes:readCodes auflisten und lesen, Bilder herunterladen.
codes:writeErstellen, ändern, dynamisch machen, löschen, Massenerstellung.
analytics:readGET /codes/:id/scans.
domains:readGET /domains (erforderlich, um domain_id sinnvoll zu nutzen).
webhooks:manageWebhooks auflisten, erstellen, testen und löschen.

OAuth 2.0 (jeder Plan, für Apps und Assistenten)

Wenn die Codes zu den Konten Ihrer Benutzer gehören sollen und nicht zu Ihrem, oder wenn ein Chat-Assistent der Client ist, verwenden Sie OAuth. Clients registrieren sich selbst; PKCE S256 ist für öffentliche Clients erforderlich; Token können mit resource= an den MCP-Server gebunden werden. Das OAuth-Rezept führt Sie hindurch.

EndpunktURLHinweise
Autorisierunghttps://qrflow.codes/oauth/authorizeSenden Sie den Benutzer hierher; er meldet sich an und drückt Erlauben.
Tokenhttps://qrflow.codes/api/oauth/tokenauthorization_code- und refresh_token-Grants. Zugriffstoken leben 1 Stunde, Aktualisierungstoken 90 Tage.
Widerrufenhttps://qrflow.codes/api/oauth/revokeRFC 7009. Benutzer können auch unter Konto › Verbundene Apps trennen.
Client registrierenhttps://qrflow.codes/api/oauth/registerRFC 7591 dynamische Registrierung, kein Konto erforderlich. Öffentliche Clients erhalten eine dyn_ client_id und müssen PKCE S256 verwenden.
Entdeckunghttps://qrflow.codes/.well-known/oauth-authorization-serverRFC 8414. Das MCP-Ressourcendokument befindet sich unter /.well-known/oauth-protected-resource.

Zugriffstoken dauern 1 Stunde, Aktualisierungstoken 90 Tage. Benutzer sehen verbundene Apps unter Konto › Verbundene Apps und können sich jederzeit trennen. Ein Token, das für https://qrflow.codes/mcp geprägt wurde, wird auf /api/v1 abgelehnt und umgekehrt.

Die Dinge, nach denen die Leute tatsächlich fragen

Bau-Rezepte

Jedes Rezept ist vollständig und direkt aus funktionierendem Code kopiert. Wählen Sie das, das zu Ihrem Stack passt; die Form ist immer dieselbe: ein serverseitiger Aufruf mit dem Schlüssel, speichern Sie id und short_url, zeigen Sie das Bild.

Next.js: eine Route, die einen Code erstellt, und eine Route, die ihn anzeigt

Wann: Sie haben eine Next.js-App (App Router) und möchten einen Button, der einen QR-Code erstellt, und eine Seite, die ihn anzeigt.

  1. Legen Sie Ihren Schlüssel in .env.local als QRFLOW_KEY. Präfixieren Sie ihn niemals mit NEXT_PUBLIC_.
  2. Fügen Sie einen POST-Routen-Handler hinzu, der den Code erstellt und id und short_url zurückgibt.
  3. Fügen Sie eine GET-Route hinzu, die das Bild proxyt, damit der Browser den Schlüssel nie sieht.
  4. Speichern Sie id und short_url in Ihrem eigenen Datensatz (Bestellung, Tisch, Produkt, Veranstaltung).
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>
  • Server Actions funktionieren genauso: Rufen Sie fetch mit dem Schlüssel innerhalb der Action auf.
  • Für Pages Router geht derselbe Code in pages/api/qr.ts mit req/res.

Den QR ohne Proxy anzeigen: short_url selbst rendern

Wann: Sie möchten das Bild sofort im Browser und benötigen QRFLOWs Rahmen oder Logo nicht darauf. Jede QR-Bibliothek funktioniert, denn der Code IST der Kurzlink

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.
  • Dies ist der schnellste Weg für eine Vorschau. Für den Druck laden Sie /codes/:id/image.svg herunter: Es enthält die gespeicherten Farben, den Rahmen, die Beschriftungen und das Logo und ist ein Vektor.
  • Wenn Sie später slug oder domain_id ändern, ändert sich short_url; rendern Sie neu.

Express oder ein beliebiger Node-Server

Wann: Ein einfaches Node-Backend.

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

Wann: Eine Nur-Fetch-Laufzeitumgebung ohne Node-Built-ins.

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_...
  • Das npm-Paket qrflow\ verwendet nur fetch und WebCrypto, läuft also unverändert in allen diesen Umgebungen.

Python: FastAPI, Flask, Django, ein Skript

Wann: Ihr Backend ist 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")

Ein QR-Code pro Bestellung, Tisch, Produkt, Ticket oder Veranstaltung

Wann: Jede Zeile in einer Ihrer Tabellen benötigt ihren eigenen Code, automatisch erstellt.

  1. Fügen Sie Ihrer Tabelle zwei Spalten hinzu: qrflow_code_id (uuid) und qr_short_url (text).
  2. Wenn eine Zeile erstellt wird, senden Sie POST /codes mit der öffentlichen URL der Zeile und einer Bezeichnung, die die Zeile benennt („Bestellung 10432“, „Tisch 7“). Speichern Sie id und short_url.
  3. Wenn sich die Seite der Zeile verschiebt (neue Domain, neuer Pfad), patchen Sie destination_data. Die gedruckten Codes funktionieren weiterhin.
  4. Wenn die Zeile ausgemustert wird, patchen Sie { paused: true }, falls etwas gedruckt wurde; löschen Sie nur, wenn nichts gedruckt wurde.
  5. Benötigen Sie Tausende auf einmal (eine Speisekarte pro Tisch für 300 Restaurants)? Verwenden Sie POST /codes/bulk in Blöcken und ordnen Sie die zurückgegebenen Codes Ihren Zeilen per Bezeichnung oder Reihenfolge zu.
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 });
  • Fair Use liegt bei 25.000 gespeicherten Codes im Business-Plan; die API stoppt beim Doppelten. Wenn Sie einen Code pro Beleg dauerhaft benötigen, sprechen Sie uns zuerst an: hello@qrflow.codes.

Ändern, wohin ein gedruckter Code führt

Wann: Eine Kampagne endete, eine Seite verschoben wurde, ein PDF ersetzt wurde, eine Saison wechselte.

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" } }'

Pausieren Sie ihn oder geben Sie ihm ein Enddatum

# 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" }'
  • Nur dynamische Codes können umgeleitet werden. Ein URL-Code, der mit einem kostenlosen Konto erstellt wurde, oder ein Wi-Fi/vCard/Text-Code antwortet mit 400 not_dynamic. Für einen URL/Telefon/E-Mail/SMS/Standort-Code in einem kostenpflichtigen Plan konvertiert POST /codes/:id/dynamic ihn, und Sie müssen neu rendern und neu drucken, da sich das Bild ändert.
  • Ein Scanner sieht das neue Ziel beim nächsten Scan. Es gibt keinen Cache, auf den man warten müsste.

Codes auf Ihrer eigenen Domain drucken

Wann: Sie möchten go.example.com/menu im Code statt qrflow.codes/q/x7k2p9a.

  1. Fügen Sie auf der Kontoseite unter „Eigene Link-Domain“ go.example.com hinzu und erstellen Sie den CNAME, der Ihnen bei Ihrem DNS-Anbieter angezeigt wird. Die Verifizierung dauert normalerweise Minuten.
  2. Ab dann verwendet die short_url jedes neuen dynamischen Codes diese Domain. Bestehende Codes wechseln ebenfalls: Ihr Bild kodierte qrflow.codes/q/..., was weiterhin umleitet, sodass nichts Gedrucktes bricht.
  3. Geben Sie Codes lesbare Namen mit slug: PATCH { "slug": "menu" } ergibt go.example.com/menu. Tun Sie dies vor dem Drucken.
  4. Im Business-Plan mit mehreren Domains listet GET /domains diese mit IDs auf; übergeben Sie domain_id bei POST oder PATCH, um pro Code zu wählen.

Benennen Sie einen Link und wählen Sie eine Domain

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

Ein Scan-Diagramm in Ihrer eigenen Verwaltung

Wann: Sie möchten Scans pro Tag, pro Land oder pro Gerät neben Ihren eigenen Zahlen sehen.

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
  • Eine Anfrage deckt bis zu 92 Tage ab; für längere Zeiträume schleifen. Daten sind in UTC.
  • Für Live-Zahlen ohne Polling abonnieren Sie einen Webhook für das Scan-Ereignis: Sie erhalten jeden Scan mit Details in Stapeln alle paar Minuten.

Webhooks in Next.js empfangen und verifizieren

Wann: Sie möchten in Ihrer eigenen Datenbank nahezu in Echtzeit wissen, wann ein Code gescannt oder geändert wird.

  1. Erstellen Sie den Webhook unter Konto › Webhooks oder mit POST /webhooks. Kopieren Sie das Geheimnis (whsec_...) einmal in QRFLOW_WEBHOOK_SECRET.
  2. Lesen Sie den rohen Body als Text, bevor Sie parsen; die Signatur deckt die exakten Bytes ab.
  3. Verifizieren Sie, dann schalten Sie auf das Ereignis. Antworten Sie schnell mit 2xx; erledigen Sie langsame Arbeit nach der Antwort oder in einer Warteschlange.
  4. Drücken Sie „Test“ auf dem Webhook, um einen signierten Ping zu empfangen und die Verkabelung zu bestätigen.
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 });
}
  • Lokal exponieren Sie Ihren Dev-Server mit einem Tunnel (cloudflared tunnel --url http://localhost:3000, oder ngrok) und verwenden diese https-URL für den Webhook, während Sie bauen.
  • Das npm-Paket erledigt dies für Sie: import { parseWebhook } from "qrflow"\ verifiziert und parst in einem Aufruf (WebCrypto, läuft also auch in Workers und Deno). Der Python-Client liefert verify_webhook.

Webhooks in Python empfangen

Wann: Flask, FastAPI oder Django empfangen dieselben Ereignisse.

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

Tausende Codes aus einer CSV

Wann: Ein Code pro SKU, pro Sitzplatz, pro Inventaretikett, pro Mailer.

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 erstellt nur dynamische URL-Codes, alle mit denselben Farben. Codes kommen in der Reihenfolge zurück, in der Sie sie gesendet haben, abzüglich abgelehnter Zeilen; im Zweifel per Bezeichnung abgleichen.
  • Webhooks erhalten ein code.created-Ereignis pro Bulk-Anfrage mit codes[] statt einem pro Code.

Lassen Sie Ihre Benutzer ihr eigenes QRFLOW-Konto verbinden (OAuth)

Wann: Sie bauen ein Produkt für andere und möchten, dass Codes in deren QRFLOW-Konten landen, nicht in Ihrem.

  1. Registrieren Sie einen Client einmal: POST https://qrflow.codes/api/oauth/register mit client_name und redirect_uris. Sie erhalten eine client_id (und ein client_secret für vertrauliche Clients).
  2. Senden Sie den Benutzer zu /oauth/authorize mit response_type=code, client_id, redirect_uri, scope, state und PKCE (code_challenge, code_challenge_method=S256).
  3. Tauschen Sie den Code bei /api/oauth/token. Speichern Sie das Refresh-Token; Zugriffstokens halten eine Stunde.
  4. Rufen Sie /api/v1 mit Authorization: Bearer <access_token> auf. Alles funktioniert genau wie mit einem Schlüssel, unter dem Plan des Benutzers.
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 sind dieselben sechs wie bei API-Schlüsseln. Fragen Sie nach dem Minimum, das Sie benötigen; der Zustimmungsbildschirm listet sie auf.
  • Wenn Ihre App ein Chat-Assistent oder Agent ist, fügen Sie resource=https://qrflow.codes/mcp zur Autorisierungsanfrage hinzu und sprechen Sie stattdessen mit dem MCP-Server; das Token wird daran gebunden.

Zapier, Make, n8n: ganz ohne Code

Wann: Sie möchten, dass Scans oder neue Codes in einem Blatt, einem Slack-Kanal oder einem CRM landen.

  1. Erstellen Sie einen Catch-Hook-Trigger (Zapier: Webhooks by Zapier › Catch Hook; Make: Custom webhook; n8n: Webhook node) und kopieren Sie seine https-URL.
  2. Fügen Sie unter Konto › Webhooks diese URL hinzu und wählen Sie die Ereignisse. Drücken Sie „Test“; der Ping erscheint im Tool und gibt ihm die Payload-Form.
  3. Ordnen Sie data.scans[] (für Scan) oder data.code (für code.*) Ihrem Blatt, Ihrer Nachricht oder Ihrem Datensatz zu.
  4. Um Codes aus diesen Tools zu erstellen, verwenden Sie deren HTTP-Modul gegen POST /codes mit dem Authorization-Header. Bewahren Sie den Schlüssel im Credential-Speicher des Tools.
  • Diese Tools können die Signatur nicht verifizieren. Die URL, die sie Ihnen geben, ist unerratbar, das ist Ihr Schutz; posten Sie sie nirgendwo.

Vibe Coding

Prompts zum Einfügen

Coding-Assistenten bauen das Richtige, wenn ihnen die Regeln im Voraus mitgeteilt werden. Diese Prompts tragen die Regeln. Fügen Sie einen ein, füllen Sie die Klammer aus, und der Assistent liest die Markdown-Referenz, bevor er eine Zeile schreibt.

QR-Codes zu meiner App hinzufügen

Claude, ChatGPT, Cursor, Codex, Windsurf, Copilot Chat: in den Chat einfügen

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"].

Ihr Repo über QRFLOW unterrichten

Einfügen in CLAUDE.md, AGENTS.md, .cursorrules oder .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.

In Lovable, Bolt, v0, Replit und anderen App-Buildern

Frontend-zuerst-Builder, die Ihnen ein Backend geben (Supabase, serverlose Funktionen)

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

Ein benutzerdefinierter GPT, der meine Codes verwaltet

ChatGPT › GPT erstellen › Aktionen

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).

Dinge, die Sie sagen sollten, sobald der Connector aktiv ist

Claude, ChatGPT, Claude Code mit verbundenem QRFLOW-MCP-Server

"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-Server

Verwenden Sie es von Claude, ChatGPT, Cursor und Claude Code

QRFLOW ist ein MCP-Server unter https://qrflow.codes/mcp. Verbinden Sie ihn einmal, melden Sie sich an, und sagen Sie dann Dinge wie „mach einen QR-Code für unsere Herbstmenü-Seite, benannt menu auf meiner Domain“, „richte den Code des Lobby-Plakats auf die neue Seite“ oder „wie viele Scans hat der Flyer letzte Woche bekommen, nach Land?“. Der Assistent erhält dieselben Tools, die diese API bietet, unter denselben Regeln, und die Codes landen in Ihrem Dashboard mit mcp als Quelle.

Kein Entwickler? Die Version in einfachen Worten mit den genauen Klicks für jeden Assistenten finden Sie unter QR-Codes mit Ihrem KI-Assistenten erstellen.

Verbinden

Anpassen › Connectors › Benutzerdefinierten Connector hinzufügen › Adresse einfügen oder „Verbinden“ im QRFLOW-Verzeichniseintrag drücken. Claude öffnet eine QRFLOW-Anmeldung; drücken Sie „Zulassen“. Funktioniert in jedem Plan.

https://qrflow.codes/mcp

Einstellungen › Sicherheit und Anmeldung › Entwicklermodus ein, dann Einstellungen › Plugins › + › Adresse einfügen; melden Sie sich an, wenn Sie gefragt werden. Plus, Pro, Team, Enterprise und Edu.

https://qrflow.codes/mcp

Ein Befehl, dann /mcp zum Anmelden. Fügen Sie einen Business-Schlüssel als Header hinzu, um die Anmeldung zu überspringen.

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, jeder MCP-Client

Fügen Sie einen HTTP-Server unter der URL hinzu. Die OAuth-Anmeldung erfolgt im Browser; oder übergeben Sie einen Authorization-Header mit einem Schlüssel.

{
  "mcpServers": {
    "qrflow": { "type": "http", "url": "https://qrflow.codes/mcp" }
  }
}

Ihr eigener Agent (Anthropic- oder OpenAI-SDK)

Richten Sie den MCP-Connector oder das Tool auf die URL mit einem Business-Schlüssel als Bearer; kein Browser-Flow nötig.

// Anthropic Messages API, MCP connector
mcp_servers: [{ type: "url", url: "https://qrflow.codes/mcp", name: "qrflow", authorization_token: process.env.QRFLOW_KEY }]

Was der Assistent tun kann

ToolWas es tutUmfang
list_code_kindsJede Art von Code mit seinen Feldern und dem benötigten Plan. Der Assistent ruft dies auf, bevor er etwas Ungewöhnliches erstellt.profile
list_domainsIhre Link-Domains, die Standard-Domain und ihre IDs.domains:read
get_qr_imageEin PNG, das der Assistent anzeigen oder speichern kann, plus die SVG-URL für den Druck.codes:read
get_accountWer angemeldet ist, Plan, Limits.profile

Wie es sicher bleibt

  • Der Assistent hält nur ein Token für Ihr Konto, ausgestellt, nachdem Sie „Zulassen“ auf einer QRFLOW-Seite gedrückt haben. Trennen Sie es jederzeit unter Konto › Verbundene Apps.
  • Tokens sind an den MCP-Server gebunden; sie können nicht gegen die REST-API wiederverwendet werden.
  • Jeder Schreibvorgang durchläuft dieselbe Validierung wie das Dashboard: Whitelist-Ziele, Planprüfungen, Fair-Use-Obergrenzen.
  • Destruktive Tools beschreiben sich sorgfältig: delete_qr_code weist das Modell an, das Pausieren zu bevorzugen, wenn ein Druck existiert.
  • Discovery-Dokumente liegen unter /.well-known/oauth-authorization-server und /.well-known/oauth-protected-resource; Registrierung ist RFC 7591; nur PKCE S256.

SDKs und die OpenAPI-Spezifikation

  • TypeScript / JavaScript: npm install qrflow (npm). Null Abhängigkeiten, ESM und CommonJS, vollständige Typen; läuft in Node 18+, Bun, Deno und Workers. Wiederholt 429s für Sie und liefert verifyWebhook / parseWebhook.
  • Python 3.9+, nur Standardbibliothek: qrflow.py.
  • OpenAPI 3.1: /api/v1/openapi.json. Importieren Sie in Postman oder Insomnia, generieren Sie einen Client in jeder Sprache oder hängen Sie es an eine ChatGPT-Aktion an.
  • Beide Clients werfen einen typisierten Fehler (QRFlowError mit status, code, message, retryAfter) und liefern einen Webhook-Verifizierer. Die einzeilige TypeScript-Quelle ist weiterhin unter /sdk/qrflow.ts, falls Sie sie lieber selbst einbinden möchten.
TypeScriptPythonAufrufe
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)Die Bildadresse (mit dem Schlüssel abrufen)
verifyWebhook(raw, header, secret)verify_webhook(raw, header, secret)Signaturprüfung für Zustellungen

Endpunkt-Referenz

Base-URL https://qrflow.codes/api/v1. Bodies und Antworten sind JSON. Daten sind ISO 8601 in UTC. Sende bei PATCH nur die Felder, die sich ändern.

GETprofile

Plan, Feature-Flags und die Limits, die für dieses Konto gelten, sowie die Scopes des Schlüssels.

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

Native Typen (url, wifi, vcard, email, phone, sms, text, location) und die rund 50 Untertypen (Instagram, Google-Rezension, Wi-Fi, App-Store …), jeweils mit den benötigten Feldern und dem erforderlichen Plan. Kein Schlüssel nötig.

curl https://qrflow.codes/api/v1/catalog

GETcodes:read

Neueste zuerst.?limit= bis zu 100,?q= durchsucht Labels.

curl "https://qrflow.codes/api/v1/codes?limit=20&q=menu" \
  -H "Authorization: Bearer $QRFLOW_KEY"

POSTcodes:write

Gleiche Regeln wie Speichern auf der Website: url-, phone-, email-, sms- und location-Codes sind in kostenpflichtigen Plänen dynamisch; Wi-Fi-, vCard- und Text-Codes tragen ihren Inhalt im Muster. Setze eine Untertyp-ID in destination_data.subtype, um zum Beispiel einen Google-Rezensions-Code zu erstellen. Optional wählt domain_id aus, mit welcher deiner Link-Domains der Code gedruckt wird (GET /domains listet sie).

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

Der Code mit seiner Scan-Anzahl, dem Kurzlink und der Bildadresse.

curl https://qrflow.codes/api/v1/codes/$ID \
  -H "Authorization: Bearer $QRFLOW_KEY"

PATCHcodes:write

Beliebig davon: destination_data (nur bei dynamischen Codes, der Druck bleibt gültig), label, paused, expires_at (ISO oder null), slug (ein Linkname auf deiner Domain), domain_id (mit welcher deiner Link-Domains dieser Code gedruckt wird; null = Kontostandard), fg_color, bg_color, frame_style, frame_caption, frame_caption2. Sende nur die Felder, die du änderst.

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

Endgültig weg, einschließlich der Scan-Historie. Der gedruckte Link eines dynamischen Codes funktioniert nicht mehr. Bevorzuge paused: true, wenn der Druck noch im Umlauf ist.

curl -X DELETE https://qrflow.codes/api/v1/codes/$ID \
  -H "Authorization: Bearer $QRFLOW_KEY"
204 No Content

POSTcodes:write

Das gedruckte Muster ändert sich (es kodiert jetzt den Kurzlink), also rendere das Bild danach neu.

curl -X POST https://qrflow.codes/api/v1/codes/$ID/dynamic \
  -H "Authorization: Bearer $QRFLOW_KEY"

GETcodes:read

Druckfertiges SVG mit Rahmen und Farben.?size= setzt die Modul-Rasterbreite in px; die Datei skaliert trotzdem verlustfrei.

curl https://qrflow.codes/api/v1/codes/$ID/image.svg \
  -H "Authorization: Bearer $QRFLOW_KEY" -o code.svg

GETanalytics:read

?from= und?to= (ISO-Daten, bis zu 92 Tage, Standard die letzten 30) und?group= day, device, country, city, browser, os oder referrer. Dieselben Zahlen wie auf der Analyse-Seite.

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

Bis zu 2.000 URL-Codes in einem Aufruf, alle dynamisch. Zählt gegen dasselbe monatliche Bulk-Kontingent wie die Bulk-Seite (10.000 bei Business). Zeilen, die keine Webadressen sind, kommen in rejected zurück; der Rest wird erstellt.

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

Deine verbundenen Domains, deren Status und welche dynamische Codes standardmäßig druckt (default_base). Übergib die ID einer Domain als domain_id bei einem Code, um diesen mit einer anderen zu drucken.

curl https://qrflow.codes/api/v1/domains \
  -H "Authorization: Bearer $QRFLOW_KEY"

GETwebhooks:manage

Deine Webhooks mit ihren Ereignissen, letztem Status und Fehleranzahl.

curl https://qrflow.codes/api/v1/webhooks \
  -H "Authorization: Bearer $QRFLOW_KEY"

POSTwebhooks:manage

url muss https auf einem öffentlichen Host sein; events ist eines von scan, code.created, code.updated, code.deleted. Das Signing-Secret wird einmal zurückgegeben.

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

Sendet jetzt einen signierten Ping und meldet die Antwort.

curl -X POST https://qrflow.codes/api/v1/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $QRFLOW_KEY"

DELETEwebhooks:manage

Stoppt alle Zustellungen, einschließlich geplanter Wiederholungen.

curl -X DELETE https://qrflow.codes/api/v1/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $QRFLOW_KEY"
204 No Content

GETpublic

Rahmen-IDs und was jeder benötigt (Beschriftung, zweite Zeile), gruppiert wie im Customizer. Kein Schlüssel nötig.

curl https://qrflow.codes/api/v1/frames

Das Code-Objekt

Jeder Endpunkt, der einen Code berührt, gibt dieselbe Struktur zurück. Ignoriere Felder, die du nicht kennst; im Laufe der Zeit werden neue hinzugefügt.

FeldTypBedeutung
iduuidStabile ID. Verwende sie in jedem anderen Aufruf.
labelstring | nullDer Name im Dashboard. Bis zu 120 Zeichen. Durchsuchbar mit?q=.
kindstringDie Katalog-ID: url, wifi, instagram, googlereview, … kind_label ist der menschenlesbare Name.
typestringDie Kodierung: url, text, wifi, vcard, email, phone, sms, location.
destination_dataobjectDie Felder, die du gesendet hast (plus subtype für Arten). destination ist eine einzeilige Zusammenfassung davon.
dynamicbooleanTrue, wenn Scans über QRFLOW laufen und das Ziel geändert werden kann. dynamic_capable sagt, ob dieser Typ in einem kostenpflichtigen Plan dynamisch sein könnte.
short_codestringSieben Zeichen, ändert sich nie.
short_urlstringWas für einen dynamischen Code gedruckt wird. Enthält deine Domain und den Slug, wenn gesetzt.
domain_iduuid | nullMit welcher Link-Domain dieser Code gedruckt wird; null bedeutet Kontostandard.
fg_color, bg_colorhexModul- und Hintergrundfarben.
has_logobooleanEin Logo wurde im Dashboard hinzugefügt; image.svg enthält es.
frame_style, frame_caption, frame_caption2string | nullRahmen-ID und Beschriftungen, wie im Customizer.
scansintegerLebenslange Scan-Anzahl.
created_at, updated_atISO 8601UTC.
manage_urlurlDie Seite des Codes im Dashboard, für einen „In QRFLOW öffnen“-Link.
image_urlurlGET /codes/:id/image.svg. Benötigt den Authorization-Header; keine öffentliche Bild-URL.
svg_download_url, png_download_urlurlDasselbe SVG (Rahmen, Farben, Logo) und ein einfaches PNG über signierte Links, die 24 Stunden ohne Header funktionieren: für <img>-Tags, Skripte und Assistenten, die eine Datei speichern. download_expires_at sagt, wann sie ablaufen; jeder Lesevorgang des Codes gibt frische zurück.

Andere Strukturen: 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, plus secret einmal), Me (id, email, plan, paid, features, limits, auth, scopes) und Error (error, message). Das OpenAPI-Dokument hat jede Eigenschaft typisiert.

Business

Webhooks

QRFLOW ruft deine https-URL auf, wenn etwas passiert. Erstelle einen unter Konto › Webhooks oder mit POST /webhooks; du erhältst das Signing-Secret einmal. Bis zu 10 pro Konto.

EreignisWannDaten
scanGebündelt: alle paar Minuten alle neuen Scans seit der letzten Zustellung, bis zu 500 pro Aufruf.count, from, to, scans[] mit code_id, label, short_code, slug, scanned_at, device, country, city, referrer, browser, os, language
code.createdSofort über API und Assistenten; innerhalb von Minuten über das Dashboard. Ein Bulk-Aufruf sendet ein Ereignis mit bulk: true und codes[].code, source
code.updatedGleiche Zeitsteuerung. Deckt Ziel, Label, Pause, Ablauf, Linkname, Domain, Farben, Rahmen und Umwandlung in dynamisch ab.code, changed[] (die geänderten Feldnamen)
code.deletedGleiche Zeitsteuerung.code: { id, label, short_code, slug }
pingWenn du Test drückst.webhook_id, message

Was ankommt

Jede Nutzlast ist { id, event, created_at, data }. id ist über Wiederholungen einer Zustellung stabil, sodass du darauf deduplizieren kannst.

{
  "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

Signatur prüfen

X-QRFLOW-Signature: t=<unix seconds>,v1=<hex>. Berechne HMAC-SHA256 über ${t}.${rawBody} mit deinem Secret und vergleiche es in konstanter Zeit mit v1; lehne ab, wenn t mehr als fünf Minuten alt ist. Verwende die rohen Bytes, die du empfangen hast, niemals ein neu serialisiertes Objekt. Funktionierende Empfänger für Next.js und Python sind in den Rezepten, und beide SDKs enthalten den Helfer.

Zustellregeln

  • Antworte innerhalb von 8 Sekunden mit einem beliebigen 2xx. Erledige die Arbeit, nachdem du geantwortet hast.
  • Alles andere wird nach 1, 5, 15, 60, 240 und 720 Minuten erneut versucht.
  • Zwanzig aufeinanderfolgende Fehler schalten den Webhook ab und benachrichtigen den Kontoinhaber per E-Mail. Schalte ihn wieder ein, sobald der Empfänger repariert ist; geplante Wiederholungen werden fortgesetzt.
  • URLs müssen https auf einem öffentlichen Host sein. localhost, private Bereiche und qrflow.codes selbst werden abgelehnt. Verwende während der Entwicklung einen Tunnel.
  • Drücke Test, um einen signierten ping zu empfangen und den Status zu sehen, den dein Server geantwortet hat.

Fehler

Jeder Fehler ist { "error": "<code>", "message": "<what to do>" } mit dem untenstehenden Status. Die Meldung ist für eine Person geschrieben; zeige sie.

StatuserrorBedeutung

Symptom, Ursache, Lösung

Fehlerbehebung

401 invalid_token bei jedem Aufruf

WarumDer Header ist falsch oder der Schlüssel ist nicht aktiv.

LösungSende genau Authorization: Bearer qrf_live_… (ein Leerzeichen, kein Doppelpunkt). Prüfe, ob der Schlüssel nicht unter Konto › API-Schlüssel widerrufen wurde. Wenn du ihn aus einem Chat oder Dokument kopiert hast, achte auf einen abschließenden Punkt oder ein intelligentes Anführungszeichen.

401 auf /api/v1 mit einem Token, das auf dem MCP-Server funktioniert

WarumTokens, die für https://qrflow.codes/mcp ausgestellt wurden, sind daran gebunden.

LösungVerwende einen API-Schlüssel für REST oder führe einen zweiten OAuth-Flow ohne resource= aus, um ein Token für die REST-API zu erhalten.

402 upgrade_required beim Erstellen eines Schlüssels oder Webhooks

WarumBeides sind Business-Funktionen.

LösungUpgrade auf /pricing oder verwende den MCP-Server, der auf jedem Plan über die Anmeldung funktioniert.

402 auf POST /codes von einer OAuth-App

WarumDer Plan des Benutzers enthält nicht, was die App angefordert hat (einen dynamischen Code, eine Domain).

LösungLies zuerst GET /me features und passe dich an: erstelle den Code trotzdem (er wird auf Free statisch) oder teile dem Benutzer mit, was der Plan benötigt.

403 insufficient_scope

WarumScopes werden beim Erstellen eines Schlüssels festgelegt.

LösungErstelle einen neuen Schlüssel mit den benötigten Scopes und widerrufe den alten. Für OAuth fordere den Scope in der authorize-Anfrage an.

400 not_dynamic bei PATCH destination_data

WarumDer Code ist statisch: auf Free erstellt oder ein Wi-Fi-/vCard-/Text-Typ.

LösungFür url/phone/email/sms/location in einem kostenpflichtigen Plan: POST /codes/:id/dynamic, dann erneut herunterladen und neu drucken (das Bild ändert sich). Wi-Fi, vCard und Text können nie dynamisch sein; erstelle stattdessen einen url-Code, der eine Seite öffnet.

400 no_domain beim Setzen von slug

WarumLinknamen leben auf deiner Domain.

LösungVerbinde und verifiziere zuerst eine Domain auf der Konto-Seite. Auf qrflow.codes/q ist der Pfad immer der short_code.

409 conflict bei slug

WarumEin anderer deiner Codes hat diesen Namen.

LösungGET /codes?q= um ihn zu finden, oder wähle einen anderen Namen. Namen sind pro Konto, nicht global.

CORS-Fehler in der Browser-Konsole

WarumDie API akzeptiert nur Server-zu-Server-Aufrufe (und Canva). Das ist beabsichtigt: Ein Schlüssel in einer Webseite ist ein geleakter Schlüssel.

LösungVerschiebe den Aufruf in einen Route-Handler, eine Server-Action, eine Edge-Funktion oder ein Backend und rufe diesen von der Seite aus auf.

Das Bild zeigt ein QRFLOW-Wasserzeichen

WarumDas Konto ist im Free-Plan.

LösungKostenpflichtige Pläne entfernen es. Free ist für den eigenen Generator der Website gedacht.

short_url sagt immer noch qrflow.codes/q/…, nachdem ich meine Domain hinzugefügt habe

WarumDie Domain ist noch nicht verifiziert oder ihr CNAME ist falsch.

LösungPrüfe den Status auf der Konto-Seite oder mit GET /domains (Status muss verified sein). Bestehende Codes wechseln automatisch, sobald er es ist.

image_url gibt 401 in einem <img>-Tag

WarumEs benötigt den Authorization-Header, den ein <img> nicht senden kann.

LösungVerwende svg_download_url oder png_download_url aus demselben Code-Objekt: signierte Links, die 24 Stunden ohne Header funktionieren. Für etwas Dauerhaftes proxye image_url über deinen Server (siehe Next.js-Rezept) oder kodiere short_url selbst.

Ich brauche ein PNG, kein SVG

WarumDas SVG trägt Rahmen und Logo; das PNG ist der einfache Code.

LösungGET /codes/:id/image.png (Bearer oder die signierte png_download_url) gibt ein PNG zurück, 256 bis 2048 px. Für ein PNG mit Rahmen konvertiere das SVG mit sharp oder resvg (sharp(svgBuffer).png().toBuffer()).

Mein Assistent sagte, der Bild-Endpunkt habe ihn abgelehnt und er habe den Code selbst gezeichnet

WarumEr hat image_url abgerufen, das einen Bearer benötigt.

LösungJeder Code trägt jetzt png_download_url und svg_download_url, und get_qr_image gibt sie zurück; der Assistent kann diese ohne Anmeldung mit curl abrufen. Ein lokal gezeichneter Code, der dieselbe short_url kodiert, funktioniert weiterhin und zählt weiterhin Scans, aber ihm fehlen Rahmen und Logo.

Webhook kommt nie an

WarumURL-Regeln oder der Empfänger.

LösungDie URL muss https auf einem öffentlichen Host sein (kein localhost, keine privaten IPs, nicht qrflow.codes). Drücke Test auf dem Webhook: Das Ergebnis zeigt den Status, den dein Server geantwortet hat. Scan-Ereignisse werden gebündelt und können bis zu etwa fünf Minuten dauern; code.*-Ereignisse aus dem Dashboard werden ebenfalls für ein paar Minuten in die Warteschlange gestellt, während API- und MCP-Schreibvorgänge sofort zustellen.

Signatur verifiziert nie

WarumDu hast einen neu serialisierten Body signiert. FixVerify anhand der exakt empfangenen Rohbytes, vor dem JSON-Parsing. Verwenden Sie in Express express.raw({ type: 'application/json' }) auf dieser Route; im Next.js App Router verwenden Sie await req.text(); in Flask request.get_data(). Berechnen Sie dann HMAC-SHA256 von ${t}.${raw}\.

Webhook hat sich selbst deaktiviert

WarumZwanzig aufeinanderfolgende Fehlschläge.

FixBeheben Sie den Empfänger und aktivieren Sie ihn dann wieder (Konto › Webhooks, oder löschen und neu erstellen). Sie wurden per E-Mail benachrichtigt, als es passierte. In der Warteschlange befindliche Wiederholungsversuche werden fortgesetzt.

Doppelte Webhook-Zustellungen

WarumEin langsames 2xx (über 8 Sekunden) gilt als Fehlschlag und wird erneut versucht.

FixAntworten Sie zuerst, verarbeiten Sie danach. Deduplizieren Sie anhand der id der Nutzlast, die über Wiederholungsversuche hinweg stabil ist.

429 rate_limited während eines Imports

Warum600 Anfragen pro Minute und Schlüssel.

FixVerwenden Sie POST /codes/bulk (2.000 Codes in einer Anfrage) anstelle von einem POST pro Code, oder warten Sie Retry-After Sekunden.

Ich habe einen Code gelöscht und das gedruckte Poster zeigt jetzt 'Code not found'

WarumLöschen ist dauerhaft und beendet den Link.

FixEs gibt kein Rückgängig. Verwenden Sie beim nächsten Mal PATCH { paused: true }; ein pausierter Code zeigt eine freundliche Seite und kann fortgesetzt werden.

Mein Schlüssel funktionierte nach dem Downgrade nicht mehr

WarumSchlüssel funktionieren 30 Tage nach Verlassen von Business weiter, dann antworten sie mit 402.

FixAbonnieren Sie erneut; nichts wurde gelöscht, und dieselben Schlüssel funktionieren wieder.

Etwas nicht auf der Liste? hello@qrflow.codes, mit der genauen Anfrage und dem JSON-Fehler, den Sie erhalten haben. Business-Konten erhalten Priorität.

Limits und faire Nutzung

Limit
Anfragen pro Minute, pro Schlüssel600. 429 mit Retry-After darüber hinaus.
Schlüssel pro Konto10
Webhooks pro Konto10
Gespeicherte Codes (faire Nutzung)1.000 Premium, 25.000 Business; die API stoppt beim Doppelten.
Bulk500/Monat (500 pro Anfrage) Premium; 10.000/Monat (2.000 pro Anfrage) Business.
Link-Domains1 Premium, 5 Business
ScansUnbegrenzt. Eine Check-in-E-Mail bei 100.000 Scans pro Code pro Monat bei Premium, 1.000.000 bei Business; nichts wird gedrosselt.
Scan-Analysefenster92 Tage pro Anfrage
Listenseitengröße100 (?limit=)
Label / Bildunterschriften / Slug120 / 60 / 40 Zeichen
Webhook-Timeout und Wiederholungen8 Sekunden; Wiederholungen nach 1, 5, 15, 60, 240 und 720 Minuten; aus nach 20 aufeinanderfolgenden Fehlschlägen.
Nach Verlassen von BusinessSchlüssel und Webhooks funktionieren 30 Tage weiter, dann 402. Nichts wird gelöscht.

Faire Nutzung ist das, wofür der Plan bepreist ist. Nichts wird bei der Zahl gedrosselt; die API stoppt beim Doppelten und eine Person kontaktiert Sie zuerst. Höhere Volumina: hello@qrflow.codes.

Sicherheit, für Sie und für die Personen, die scannen

Wie QRFLOW Ihr Konto schützt

  • Schlüssel werden einmal angezeigt und als SHA-256-Hashes gespeichert. Niemand bei QRFLOW kann einen Schlüssel zurücklesen; wenn Sie ihn verlieren, erstellen Sie einen neuen.
  • Jede Anfrage ist auf das Konto beschränkt, zu dem der Schlüssel gehört. Eine Code-ID aus einem anderen Konto ist eine 404, niemals ein Leck.
  • Bereiche sind pro Schlüssel festgelegt, sodass ein Schlüssel für ein Reporting-Dashboard keine Codes erstellen oder löschen kann.
  • 600 Anfragen pro Minute pro Schlüssel; darüber hinaus ist es ein sauberes 429, keine Verlangsamung für alle.
  • Ziele sind auf eine Whitelist gesetzt: http, https, mailto, tel, sms, geo und eine kurze Liste von App-Schemata (whatsapp, tg, signal, spotify, App-Stores). javascript:, data: und file: werden bei der Erstellung abgelehnt, sodass eine kompromittierte Integration Ihre Codes nicht in einen Angriff verwandeln kann.
  • Webhook-URLs müssen https auf öffentlichen Hosts sein; QRFLOW ruft niemals private Netzwerke oder sich selbst auf. Jede Zustellung ist signiert und jede Nutzlast hat eine stabile ID.
  • OAuth-Clients registrieren sich mit PKCE S256 und Token sind an den Server gebunden, für den sie ausgestellt wurden; ein Token für den MCP-Server kann nicht auf der REST-API wiederverwendet werden.
  • Jeder kann einen Schlüssel widerrufen oder eine App auf der Kontoseite trennen; die Wirkung ist sofort.

Was Sie auf Ihrer Seite tun sollten

  • Umgebungsvariablen, niemals Quellcode. Wenn ein Schlüssel in eine Git-Historie gelangt, widerrufen Sie ihn.
  • Nur serverseitig. Die API lehnt Browser-Ursprünge ab, aber Ihre eigenen Endpunkte, die sie umschließen, benötigen ebenfalls Authentifizierung, sonst kann jeder Codes auf Ihre Rechnung erstellen.
  • Geben Sie jeder Integration ihren eigenen Schlüssel mit den Bereichen, die sie benötigt, benannt nach der Integration. Das Widerrufen eines Schlüssels betrifft dann nur eine Sache.
  • Verifizieren Sie Webhook-Signaturen und lehnen Sie Zeitstempel ab, die älter als fünf Minuten sind.
  • Wenn die Daten Ihrer Benutzer in Labels oder Ziele fließen, denken Sie daran, dass QRFLOW sie speichert; halten Sie personenbezogene Daten nach Möglichkeit aus Labels heraus.

Was Scans aufzeichnen und was nicht

  • Jede Weiterleitung speichert Gerätetyp, Land, Stadt, Referrer, Browser, Betriebssystem und Sprache, abgeleitet aus der Anfrage, sowie einen Einweg-Hash aus Code + Tag + IP + User-Agent, damit der Eigentümer eindeutige Besucher zählen kann. Der Hash kann nicht in eine Adresse zurückverwandelt werden.
  • Es werden keine Cookies auf der Person gesetzt, die scannt, und die IP-Adresse selbst wird nicht mit dem Scan gespeichert. Bekannte Bots und Link-Preview-Crawler werden übersprungen.
  • Das Löschen eines Codes löscht seine Scans. Das Löschen des Kontos löscht alles.
  • Volltext: https://qrflow.codes/privacy und https://qrflow.codes/terms.

Versionierung und Stabilität

Die API ist im Pfad versioniert: /api/v1. Innerhalb von v1 fügen wir Felder, Endpunkte, Arten und Ereignisse hinzu; wir entfernen oder benennen nichts um, und unbekannte Felder in Antworten sollten von Ihrem Code ignoriert werden.

Wenn eine Änderung jemals v1 brechen muss, wird sie als /api/v2 ausgeliefert und v1 läuft mindestens zwölf Monate weiter. Schlüsselinhaber werden 90 Tage im Voraus per E-Mail über Einstellungen informiert.

Der MCP-Server folgt derselben Regel für seine Tools: Argumente werden nur hinzugefügt, und jedes Tool behält seinen Namen.

Das OpenAPI-Dokument unter /api/v1/openapi.json und das Markdown unter /llms-full.txt werden aus dem Code generiert, der die API bedient, sodass sie beschreiben, was heute live ist.

Fragen, die Entwickler stellen

Muss ich bezahlen, um die QRFLOW-API zu nutzen?

API-Schlüssel sind im Business-Plan enthalten, 29 $ pro Monat, monatlich kündbar. Der MCP-Server (Claude, ChatGPT, Cursor, Claude Code) und OAuth für Ihre eigene App funktionieren auf jedem Plan über die Anmeldung, und was sie erstellen dürfen, folgt dem Plan. GET /catalog, GET /frames und /preview.svg benötigen überhaupt keinen Schlüssel.

Kann ich QR-Codes kostenlos über die API generieren?

Nicht mit einem Schlüssel. Für ein einfaches statisches Bild erledigt der kostenlose Generator auf qrflow.codes oder eine beliebige Open-Source-QR-Bibliothek die Arbeit. Die API ist für dynamische Codes, Ihre eigene Domain, Analysen, Bulk und Webhooks gedacht, das ist es, wofür ein kostenpflichtiges Konto ist.

Kann ich die API aus dem Browser aufrufen?

Nein. Sie lehnt Browser-Ursprünge ab, sodass ein Schlüssel niemals in einer Webseite landen kann. Rufen Sie sie aus einem Routen-Handler, einer Server-Action, einer Edge-Funktion oder einem Backend auf, und rufen Sie das von Ihrer Seite aus auf.

Welche Bildformate erhalte ich?

SVG mit Ihren Farben, Rahmen, Bildunterschriften und Logo (GET /codes/:id/image.svg, nominal 256 bis 4096 px) und ein einfaches PNG (GET /codes/:id/image.png, 256 bis 2048 px). Beide akzeptieren einen Bearer oder die signierte svg_download_url / png_download_url, die jedes Code-Objekt trägt und die 24 Stunden ohne Header funktionieren. Das MCP-Tool get_qr_image gibt das PNG inline plus beide Links zurück.

Kann ich einen QR-Code nach dem Drucken ändern?

Ja, wenn er dynamisch ist (url, phone, email, sms, location in einem kostenpflichtigen Plan). PATCH /codes/:id mit einem neuen destination_data; das Bild ändert sich nicht, der nächste Scan geht an den neuen Ort. Wi-Fi-, vCard- und Text-Codes tragen ihren Inhalt im Bild und können nicht geändert werden.

Was ist der Unterschied zwischen short_url und dem Ziel?

short_url ist der Link im Bild (go.example.com/menu). Das Ziel ist, wohin dieser Link weiterleitet (https://example.com/menu-fall). Sie drucken short_url einmal und ändern das Ziel so oft Sie möchten.

Können Codes meine eigene Domain verwenden?

Ja. Premium verbindet 1 Domain, Business 5; Sie fügen einen CNAME hinzu und verifizieren auf der Kontoseite. Business wählt eine Domain pro Code mit domain_id. Linknamen (Slug) erzeugen lesbare Pfade darauf.

Was zeichnet ein Scan über die Person auf, die scannt?

Gerätetyp, Land, Stadt, Referrer, Browser, Betriebssystem und Sprache, aus der Anfrage, plus einen Einweg-Tages-Hash für eindeutige Besucherzählungen. Keine Cookies, und die IP-Adresse wird nicht gespeichert. Genug für ein Diagramm, nicht genug, um jemanden zu identifizieren. Details: https://qrflow.codes/privacy#scans

Gibt es ein npm- oder PyPI-Paket?

npm: npm install qrflow\ (https://www.npmjs.com/package/qrflow), null Abhängigkeiten, ESM und CommonJS, vollständige TypeScript-Typen, läuft in Node 18+, Bun, Deno und Workers; es umschließt jeden Endpunkt, wiederholt 429s und enthält verifyWebhook/parseWebhook. Python: ein einzelner Datei-Client unter https://qrflow.codes/sdk/qrflow.py (nur Standardbibliothek) mit verify_webhook; ein PyPI-Paket folgt.

Funktioniert es mit Claude, ChatGPT, Cursor und Claude Code?

Ja. QRFLOW ist ein MCP-Server unter https://qrflow.codes/mcp. Fügen Sie ihn als Connector hinzu, melden Sie sich einmal an und fragen Sie in einfachen Worten. Elf Tools decken Erstellen, Bearbeiten, Pausieren, Benennen, Bulk, Analysen, Bilder und Domains ab.

Können meine eigenen Benutzer ihre QRFLOW-Konten mit meiner App verbinden?

Ja, mit OAuth 2.0. Registrieren Sie einen Client unter /api/oauth/register (kein Konto erforderlich), senden Sie Benutzer mit PKCE an /oauth/authorize und rufen Sie die API mit ihrem Token auf. Codes landen in ihrem Konto unter ihrem Plan.

Wie teste ich Webhooks auf localhost?

Stellen Sie Ihren Dev-Server mit einem Tunnel bereit (cloudflared oder ngrok) und verwenden Sie dessen https-Adresse als Webhook-URL, drücken Sie dann Test unter Konto › Webhooks, um einen signierten Ping zu erhalten. Webhook-URLs müssen öffentliches https sein; localhost und private Adressen werden abgelehnt.

Was passiert mit meiner Integration, wenn ich Business kündige?

Schlüssel und Webhooks funktionieren 30 Tage weiter, dann antworten sie mit 402. Codes, Scans und Domains bleiben im Konto. Eine erneute Anmeldung aktiviert alles wieder mit denselben Schlüsseln.

Wie erstelle ich einen Google-Review-, Instagram-, Wi-Fi- oder PDF-Code über die API?

GET /catalog listet jede Art mit ihren Feldern auf. Dann POST /codes mit dem Typ und den Feldern der Art, wobei Sie subtype für Arten hinzufügen: { type: 'url', destination_data: { subtype: 'googlereview', placeId: 'ChIJ…' } }, { type: 'wifi', destination_data: { ssid, password, encryption: 'WPA' } }, { type: 'url', destination_data: { subtype: 'instagram', handle: 'acme' } }.

Kann die API ein Logo auf einen Code hochladen?

Noch nicht. Fügen Sie das Logo im Dashboard hinzu; image.svg enthält es und has_logo zeigt Ihnen, dass es da ist. Farben, Rahmen und Bildunterschriften sind alle über die API einstellbar.

Ist die API stabil?

v1 fügt nur hinzu; es entfernt oder benennt nie um. Eine bahnbrechende Änderung würde als v2 ausgeliefert, wobei v1 mindestens zwölf Monate am Leben gehalten wird und 90 Tage Vorankündigung per E-Mail erfolgt.

Für Agenten, Tools und die Assistenten, die dies lesen

Maschinenlesbar

Alles auf dieser Seite existiert in einer Form, die Software abrufen kann. Alles wird aus dem Code generiert, der die API bedient, sodass es nie veraltet ist.

URLWas es ist
llms-full.txthttps://qrflow.codes/llms-full.txtDiese gesamte Referenz als Markdown: Konzepte, jeder Endpoint, jedes MCP-Tool, Rezepte, Fehlerbehebung, FAQ. Generiert aus derselben Quelle wie diese Seite.
developers.mdhttps://qrflow.codes/developers.mdDasselbe Dokument, für Tools, die eine .md-Datei abrufen.
llms.txthttps://qrflow.codes/llms.txtDer Seitenindex für Assistenten, der hierher verweist.
Die API auf einer Seitehttps://qrflow.codes/qr-code-apiWas die API tut, wann eine clientseitige Bibliothek die bessere Antwort ist und was sie kostet. Die Kurzversion dieser Referenz, zum Entscheiden statt zum Bauen.
openapi.jsonhttps://qrflow.codes/api/v1/openapi.jsonOpenAPI 3.1. Importierbar in Postman, Insomnia, einen Codegenerator oder eine ChatGPT-Action.
MCP-Serverhttps://qrflow.codes/mcpStreamable HTTP, OAuth mit dynamischer Registrierung oder ein Business-Schlüssel als Bearer.
server.jsonhttps://qrflow.codes/.well-known/mcp/server.jsonDas MCP-Registry-Manifest.
OAuth-Discoveryhttps://qrflow.codes/.well-known/oauth-authorization-serverRFC-8414-Metadaten; das Dokument der geschützten Ressource befindet sich daneben.
npm-Pakethttps://www.npmjs.com/package/qrflownpm install qrflow. Typisierter Client, null Abhängigkeiten, Webhook-Verifizierung. Python-Einzeldatei-Client unter https://qrflow.codes/sdk/qrflow.py.
GitHubhttps://github.com/nativecodeapps/qrflow-sdkClients, OpenAPI-Schnappschuss und ausführbare Beispiele für Next.js, Workers, Express, FastAPI- und Flask-Webhooks. Issues und PRs sind willkommen.

Fragen, Ideen, eine Art von Code, den wir hinzufügen sollten: hello@qrflow.codes. Begriffe: /terms. Datenschutz: /privacy.