QRFLOW.codes

官方

建立QR碼、重新指向已印製的動態碼、在您自己的網域上命名連結,並讀取掃描分析。

你可以用 QRFLOW Codes MCP 做什麼?

  • 建立動態 QR Code — 要求為任何 URL 產生可列印的 short_url,且目的地可在列印後隨時變更。
  • 重新指向已列印的 Code — 要求將某個 code 的 destination_data 更新為新的 URL;已列印的 code 不需重新列印即可繼續運作。
  • 取得掃描分析 — 要求依日、國家或裝置取得 Scans 明細,以了解已列印 code 的表現。
  • 暫停或設定 Code 到期 — 指示暫停某個 code,或在活動或優惠結束時設定到期日。
  • 使用自有網域命名連結 — 要求在自有網域上設定易讀的 slug,讓 code 列印為 go.yourbrand.com/menu,而非隨機路徑。

託管 MCP 伺服器

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

可安裝到 Claude Code、Codex、Cursor 等客戶端

文件

QRFLOW.codes 開發者文件

從這裡開始

QRFLOW.codes 讓您可以在印製後仍能變更 QR code,使用您自己的網域,提供掃描分析,並讓您的軟體和 AI 助理透過單一 API 完成所有操作。

QR code 是字串的圖片。大多數產生器會將您的網址放入圖片中;如果網址變更,印刷品就失效了。QRFLOW 將短連結放入圖片中(go.yourbrand.com/menu 或 qrflow.codes/q/x7k2p9a)並重新導向。您可以隨時變更指向位置,每次掃描都會被計數。這就是動態 code,也是值得使用 API 的原因。

API 完全等同於儀表板的功能:建立任何類型的 code、重新指向、為連結命名、選擇要印在哪個網域、取得掃描數據、一次建立數千個,並在事件發生時收到通知(webhooks)。相同的工具也以 MCP server 形式提供,因此 Claude、ChatGPT、Cursor 和 Claude Code 可以用自然語言操作您的帳戶。

存取方式:REST API 需要 Business API key(每月 $29,在 Account 頁面建立)或 OAuth token。MCP server 透過 OAuth 登入適用於所有方案;助理可以建立的內容依方案而定,與其他功能相同。

還在考慮是否要使用?QR code API 頁面是簡短版本:它能做什麼、客戶端函式庫做得更好的部分,以及費用。

如果您是協助他人使用 QRFLOW 建置的 AI 助理

歡迎。本頁面既是為您撰寫,也是為您協助的人撰寫。以下是良好協助的樣貌:

  1. 確認帳戶:API key 需要 Business 方案。如果他們沒有,請引導他們到 https://qrflow.codes/pricing 和 Account › API keys;不要虛構不存在的 key 或免費方案。
  2. 將 key 保存在伺服器端。從環境變數(QRFLOW_KEY)在路由處理器、server action、edge function 或後端中讀取。API 刻意拒絕瀏覽器來源(CORS),因此純前端程式碼無法呼叫。
  3. 使用 type "url" 和 destination_data.url 建立動態 code。將傳回的 id 和 short_url 儲存在他們的資料庫中。列印或顯示 short_url;之後可以用 PATCH /codes/:id 變更目的地,印刷品仍然有效。
  4. 顯示或儲存圖片:每個 Code 物件都有 png_download_url 和 svg_download_url,這些簽署連結在 24 小時內有效,無需標頭(適合一次性儲存或預覽)。若要在應用程式中永久使用,請透過您的伺服器代理 GET /codes/:id/image.svg 並帶上 key,或在用戶端使用任何 QR 函式庫編碼 short_url;追蹤仍然有效,因為連結會經過 QRFLOW。
  5. 在 PATCH 時只傳送變更的欄位。永遠不要變更已印製內容的 slug 或 domain_id;兩者都會變更已印製的連結。
  6. 當有印刷品存在時,優先使用 paused: true 而非 DELETE。刪除會使連結失效。
  7. 對於事件,使用 webhooks(Account › Webhooks 或 POST /webhooks)並使用原始請求主體驗證 X-QRFLOW-Signature 標頭。不要迴圈輪詢 GET /codes。
  8. 如果他們想從聊天中而非程式碼使用 QRFLOW,請在 https://qrflow.codes/mcp; 連線 MCP server,無需 key。
  9. 當發生錯誤時,閱讀 JSON 主體中的 error 和 message。下方的疑難排解章節將每個錯誤碼對應到修復方式。
  10. 完整的 Markdown 參考文件位於 https://qrflow.codes/llms-full.txt,OpenAPI 3.1 文件位於 https://qrflow.codes/api/v1/openapi.json.。兩者都與本頁面從相同來源產生。

人類讀者:這個區塊是我們確保您搭配的助理提供安全答案的方式。它同時也是很好的摘要。

您需要的方案

API key 是唯一僅限 Business 的功能。助理透過 MCP server 所做的一切,以及第三方應用程式透過 OAuth 所做的一切,都適用於任何方案,並遵循該方案的功能。完整價格和公平使用政策:/pricing。

FreePremium $4Business $29
API keys(從您的程式碼使用 REST)否否是,最多 10 個 key
MCP server(Claude、ChatGPT、Cursor、Claude Code)是,登入是是,登入或 key
供您自己的應用程式使用的 OAuth(使用者連線他們的 QRFLOW)是是是
動態 code(印製後變更目的地)否,僅靜態是是
您自己的連結網域否1 個網域5 個網域,每個 code 可選擇
連結名稱(go.brand.com/menu)否是是
掃描分析否是是
Webhooks否否是,最多 10 個
大量建立否每月 500 個,每次請求 500 個每月 10,000 個,每次請求 2,000 個
已儲存 code(公平使用)少量1,00025,000
團隊席位115
價格$0每月 $4每月 $29

十二個字就能完成所有工作

概念

閱讀一次,下方的每個端點就會有意義。

Static code

內容在圖片內部。Wi-Fi、聯絡人卡片(vCard)和純文字 code 永遠是靜態的,在 Free 方案上每個 code 都是。靜態 code 不需要伺服器且永不過期,但無法變更或計數。

Dynamic code

圖片包含 QRFLOW 重新導向的短連結。url、phone、email、sms 和 location code 在 Premium 和 Business 上是動態的。您可以重新指向、暫停、設定到期、重新命名和計數,而無需觸及印刷品。

short_url

動態 code 中編碼的確切字串,也是要列印的內容。在您連線網域之前是 https://qrflow.codes/q/<short_code>,之後是 https://<your domain>/<slug or short_code>.。每個 Code 物件都攜帶它。

short_code

七個隨機字元,每個 code 唯一,建立時指派且永不變更。當 code 沒有連結名稱時的備用路徑。

slug (link name)

您自己網域上的可讀路徑:go.example.com/menu。3 到 40 個小寫字母、數字和連字號,在您的帳戶內唯一,僅限已連線的網域。在列印前設定:變更它會變更已印製的連結。

Link domain

您擁有的主機名稱(go.example.com),透過 CNAME 指向 QRFLOW 並在 Account 頁面驗證。Premium 獲得一個;Business 獲得五個,並可使用 domain_id 為每個 code 選擇。最舊的啟用中網域是預設值。

Kind, type and subtype

type 是編碼方式:url、text、wifi、vcard、email、phone、sms、location。kind 是人們想要內容的友善名稱(instagram、googlereview、whatsapp、pdf、menu、appstore...)。大多數 kind 是帶有 destination_data.subtype 設定的 url code。GET /catalog 列出每個 kind 及其欄位;Code 上的 kind 告訴您它是哪一個。

destination_data

該 type 的欄位,以字串表示:網站用 { url },Wi-Fi 用 { ssid, password, encryption },Google 評論用 { placeId },Instagram 用 { handle }。在動態 code 上,您可以隨時替換它。

Scans

每次重新導向都會記錄請求本身的裝置類型、國家、城市、來源、瀏覽器、作業系統和語言,加上用於計算不重複訪客的單向每日雜湊。不設定 cookie,也不儲存 IP 位址。Code 上的 scans 是累計總數;GET /codes/:id/scans 提供細項。

Source

每個 code 都記住它的來源:dashboard、api:<key name>、mcp、canva 或 bulk。它顯示在儀表板和 webhook 負載中,因此您可以區分整合的 code 和手動建立的 code。

Workspace

Business 擁有者可以邀請最多四位隊友。Key 和 webhooks 屬於擁有者的帳戶;工作區中任何人建立的 code 對整個團隊可見。

五分鐘

快速開始

取得 key

  1. 在 Business 方案上,開啟 Account › API keys。
  2. 以用途命名("Shop backend"、"Reporting")並選擇其權限範圍。權限範圍之後無法變更;如果需要更多,請建立新的 key。
  3. 複製一次。它看起來像 qrf_live_…。將其放入名為 QRFLOW_KEY 的環境變數中。
  4. 在每個請求中將其作為 Authorization: Bearer $QRFLOW_KEY 傳送。這就是完整的驗證說明。

Key 是給伺服器用的。永遠不要將 key 放入網頁、行動應用程式或共享試算表中;如果洩漏,請撤銷並重新發行。

相同的五個步驟,分別使用 curl、TypeScript 和 Python。每個都建立動態 code、下載其圖片、變更指向位置,並讀取其掃描數據。

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 keys(Business)

每個帳戶最多 10 個,每個每分鐘 600 個請求,以雜湊儲存,僅顯示一次。Key 攜帶建立時指派的權限範圍:

權限範圍允許
profileGET /me:方案、功能、限制。每個 key 都有。
codes:read列出和讀取 code、下載圖片。
codes:write建立、變更、設為動態、刪除、大量建立。
analytics:readGET /codes/:id/scans。
domains:readGET /domains(合理使用 domain_id 所需)。
webhooks:manage列出、建立、測試和刪除 webhooks。

OAuth 2.0(任何方案,適用於應用程式和助理)

當 code 應屬於您使用者的帳戶而非您的帳戶,或當聊天助理是用戶端時,請使用 OAuth。用戶端自行註冊;公開用戶端需要 PKCE S256;token 可以使用 resource= 綁定到 MCP server。OAuth 指南逐步說明。

端點URL備註
授權https://qrflow.codes/oauth/authorize將使用者送到這裡;他們登入並按下允許。
Tokenhttps://qrflow.codes/api/oauth/tokenauthorization_code 和 refresh_token 授權。存取 token 有效期 1 小時,重新整理 token 90 天。
撤銷https://qrflow.codes/api/oauth/revokeRFC 7009。使用者也可以在 Account › Connected apps 中斷連線。
註冊用戶端https://qrflow.codes/api/oauth/registerRFC 7591 動態註冊,無需帳戶。公開用戶端獲得 dyn_ client_id,且必須使用 PKCE S256。
探索https://qrflow.codes/.well-known/oauth-authorization-serverRFC 8414。MCP 資源文件位於 /.well-known/oauth-protected-resource。

存取 token 有效期 1 小時,重新整理 token 90 天。使用者在 Account › Connected apps 中看到已連線的應用程式,並可隨時中斷連線。為 https://qrflow.codes/mcp 鑄造的 token 在 /api/v1 上會被拒絕,反之亦然。

人們實際要求的內容

建置食譜

每個食譜都是完整的,直接取自可運作的程式碼。選擇符合您技術棧的食譜;結構永遠相同:使用 key 的伺服器端呼叫、儲存 id 和 short_url、顯示圖片。

Next.js:建立 code 的路由和顯示它的路由

適用時機:您有 Next.js 應用程式(App Router),想要一個建立 QR code 的按鈕和一個顯示它的頁面。

  1. 將您的 key 放入 .env.local 作為 QRFLOW_KEY。永遠不要加上 NEXT_PUBLIC_ 前綴。
  2. 新增 POST 路由處理器,建立 code 並傳回 id 和 short_url。
  3. 新增 GET 路由代理圖片,讓瀏覽器永遠看不到 key。
  4. 將 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>
  • Server Actions 以相同方式運作:在 action 內使用 key 呼叫 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 碼

適用時機:你某個資料表中的每一列都需要自己的 QR 碼,並自動產生。

  1. 在資料表中新增兩個欄位:qrflow_code_id(uuid)和 qr_short_url(文字)。
  2. 建立列時,使用該列的公開 URL 和一個能識別該列的名稱(例如「訂單 10432」、「桌子 7」)呼叫 POST /codes。儲存 id 和 short_url。
  3. 當列的頁面移動時(新網域、新路徑),更新 PATCH destination_data。已列印的 QR 碼會繼續運作。
  4. 當列退役時,如果已有任何列印,請使用 PATCH { paused: true };只有在完全沒有列印過時才使用 DELETE。
  5. 需要一次產生數千個(例如 300 家餐廳每桌一份菜單)?分批使用 POST /codes/bulk,並透過 label 或 order 將回傳的 QR 碼對應回你的資料列。
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 });
  • 公平使用上限為 Business 方案 25,000 個已儲存 QR 碼;API 在兩倍數量時停止。如果你需要永久為每張收據產生一個 QR 碼,請先與我們聯絡:hello@qrflow.codes。

變更已列印 QR 碼的指向

適用時機:活動結束、頁面移動、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" }'
  • 只有動態 QR 碼可以重新指向。在 Free 帳戶建立的 url 型 QR 碼,或 Wi-Fi/vCard/文字型 QR 碼,會回傳 400 not_dynamic。對於付費方案上的 url/phone/email/sms/location 型 QR 碼,POST /codes/:id/dynamic 可以轉換它,而且你必須重新渲染和重新列印,因為圖片會改變。
  • 掃描器會在下次掃描時看到新的目的地。沒有需要等待的快取。

在你自己的網域上列印 QR 碼

適用時機:你希望 QR 碼中是 go.example.com/menu,而不是 qrflow.codes/q/x7k2p9a。

  1. 在帳戶頁面的「你自己的連結網域」下,新增 go.example.com,並在你的 DNS 供應商建立它顯示的 CNAME。驗證通常會在幾分鐘內完成。
  2. 從那時起,每個新的動態 QR 碼的 short_url 都會使用該網域。現有的 QR 碼也會切換:它們的圖片編碼的是 qrflow.codes/q/...,這會持續重新導向,所以已列印的內容不會中斷。
  3. 使用 slug 為 QR 碼設定可讀的名稱:PATCH { "slug": "menu" } 會產生 go.example.com/menu。請在列印前執行此操作。
  4. 在 Business 方案且有多個網域時,GET /domains 會列出它們及 id;在 POST 或 PATCH 時傳入 domain_id 以選擇每個 QR 碼的網域。

為連結命名並選擇網域

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。
  • 若想在不輪詢的情況下取得即時數據,請訂閱掃描事件的 webhook:你會每隔幾分鐘收到一批包含詳細資訊的掃描記錄。

在 Next.js 中接收 webhook 並驗證

適用時機:你希望近乎即時地在自己資料庫中得知 QR 碼被掃描或變更。

  1. 在「帳戶 › Webhooks」或使用 POST /webhooks 建立 webhook。將密鑰(whsec_...)複製到 QRFLOW_WEBHOOK_SECRET。
  2. 在解析前先以文字形式讀取原始 body;簽章涵蓋的是確切的位元組。
  3. 驗證後,再根據 event 切換處理。快速回傳 2xx;慢速工作請在回應後或放入佇列處理。
  4. 在 webhook 上按「測試」,接收一個已簽章的 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 });
}
  • 在本機開發時,使用隧道(cloudflared tunnel --url http://localhost:3000, 或 ngrok)暴露你的開發伺服器,並在建置期間使用該 https URL 作為 webhook。
  • npm 套件會幫你處理:import { parseWebhook } from "qrflow"\ 在一次呼叫中完成驗證和解析(WebCrypto,因此也能在 Workers 和 Deno 中執行)。Python 用戶端提供 verify_webhook。

在 Python 中接收 webhook

適用時機: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 產生數千個 QR 碼

適用時機:每個 SKU、每個座位、每個資產標籤、每份郵件都需要一個 QR 碼。

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 型 QR 碼,且全部使用相同的顏色。QR 碼會依照你傳送的順序回傳,扣除被拒絕的列;不確定時請用 label 比對。
  • Webhook 會為每個 bulk 請求收到一個 code.created 事件,其中包含 codes[],而不是每個 QR 碼一個事件。

讓你的使用者連接他們自己的 QRFLOW 帳戶(OAuth)

適用時機:你正在為其他人打造產品,並希望 QR 碼進入他們的 QRFLOW 帳戶,而不是你的。

  1. 註冊一次用戶端:POST https://qrflow.codes/api/oauth/register,帶上 client_name 和 redirect_uris。你會取得 client_id(機密用戶端還會取得 client_secret)。
  2. 將使用者導向 /oauth/authorize,帶上 response_type=code、client_id、redirect_uri、scope、state 和 PKCE(code_challenge、code_challenge_method=S256)。
  3. 在 /api/oauth/token 交換授權碼。儲存 refresh token;access token 有效期為一小時。
  4. 使用 Authorization: Bearer <access_token> 呼叫 /api/v1。一切運作方式與使用 API 金鑰完全相同,並受使用者的方案規範。
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
  • Scope 與 API 金鑰的六個相同。只要求你最少需要的權限;同意畫面會列出它們。
  • 如果你的應用程式是聊天助理或代理程式,請在授權請求中加入 resource=https://qrflow.codes/mcp,改與 MCP 伺服器對話;token 會綁定到該伺服器。

Zapier、Make、n8n:完全不需要程式碼

適用時機:你希望掃描記錄或新 QR 碼進入試算表、Slack 頻道或 CRM。

  1. 建立一個 catch-hook 觸發器(Zapier:Webhooks by Zapier › Catch Hook;Make:Custom webhook;n8n:Webhook node),並複製它的 https URL。
  2. 在「帳戶 › Webhooks」新增該 URL 並選擇事件。按「測試」;ping 會出現在工具中,並提供 payload 格式。
  3. 將 data.scans[](用於 scan)或 data.code(用於 code.*)對應到你的試算表、訊息或記錄。
  4. 若要從這些工具建立 QR 碼,請使用它們的 HTTP 模組呼叫 POST /codes,並帶上 Authorization 標頭。將金鑰存放在工具的憑證儲存庫中。
  • 這些工具無法驗證簽章。它們給你的 URL 是無法猜測的,這就是你擁有的保護;請勿將它張貼在任何地方。

Vibe coding

可貼上的提示詞

當事先告知規則時,程式設計助理才能建構正確的東西。這些提示詞攜帶了規則。貼上一個,填入括號內容,助理就會在寫任何程式碼之前先閱讀 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 functions)

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

一個管理我的 QR 碼的自訂 GPT

ChatGPT › 建立 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(已連接 QRFLOW MCP 伺服器)

"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 是一個位於 https://qrflow.codes/mcp 的 MCP 伺服器。連接一次、登入,然後說出像是「為我們的秋季菜單頁面製作一個 QR 碼,命名為 menu,放在我的網域上」、「將大廳海報的 QR 碼指向新頁面」或「上週傳單獲得了多少次掃描,按國家劃分?」。助理會獲得與此 API 相同的工具、受相同規則規範,而且 QR 碼會以 mcp 作為來源進入你的儀表板。

不是開發者?以簡單文字說明、包含每個助理的確切點擊步驟的版本,請見使用你的 AI 助理製作 QR 碼。

連接

Customize › Connectors › Add custom connector › 貼上地址,或在 QRFLOW 的目錄清單中按 Connect。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 用戶端

在該 URL 新增 HTTP 伺服器。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每種 QR 碼及其欄位和所需方案。助理在建立不常見的內容前會先呼叫此工具。profile
list_domains你的連結網域、預設網域及其 id。domains:read
get_qr_image助理可以顯示或儲存的 PNG,以及用於列印的 SVG URL。codes:read
get_account目前登入者、方案、限制。profile

安全性如何保障

  • 助理只會持有你的帳戶的 token,且是在你於 QRFLOW 頁面上按 Allow 後才發行。隨時可在「帳戶 › 已連接的應用程式」中斷連線。
  • Token 綁定到 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),並附帶 webhook 驗證器。單一檔案的 TypeScript 原始碼仍位於 /sdk/qrflow.ts,如果你偏好自行納入。
TypeScriptPython呼叫
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)傳遞內容的簽章檢查

端點參考

Base 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、App Store…),每種都包含其所需欄位與所需方案。無需金鑰。

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 中放入子類型 ID,即可建立例如 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 代碼,全部皆為動態。計入與「大量建立」頁面相同的每月大量配額(Business 方案為 10,000 個)。非網站位址的列會回傳在 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)。將網域的 id 作為 domain_id 傳入代碼,即可讓該代碼使用不同的網域列印。

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

GETwebhooks:manage

你的 webhook 及其事件、最後狀態和失敗次數。

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

邊框 ID 及其各自需要的內容(標題、第二行),並像自訂工具一樣分組。無需金鑰。

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

Code 物件

每個觸及代碼的端點都會回傳相同的結構。忽略你不認識的欄位;隨著時間推移會新增欄位。

欄位類型說明
iduuid穩定的 ID。在所有其他呼叫中使用它。
labelstring | null儀表板中的名稱。最多 120 個字元。可使用 ?q= 搜尋。
kindstring目錄 ID:url、wifi、instagram、googlereview,... kind_label 是人類可讀的名稱。
typestring編碼類型:url、text、wifi、vcard、email、phone、sms、location。
destination_dataobject你傳送的欄位(對於 kinds 還包含 subtype)。destination 是其單行摘要。
dynamicboolean當掃描是透過 QRFLOW 進行且目的地可以變更時為 True。dynamic_capable 表示此類型在付費方案上是否可以是動態的。
short_codestring七個字元,永不改變。
short_urlstring動態代碼要列印的內容。包含你的網域和 slug(若已設定)。
domain_iduuid | null此代碼使用哪個連結網域列印;null 表示帳戶預設。
fg_color, bg_colorhex模組和背景顏色。
has_logoboolean已在儀表板中新增標誌;image.svg 會包含它。
frame_style, frame_caption, frame_caption2string | null邊框 ID 和標題,如同自訂工具中的設定。
scansinteger累計掃描次數。
created_at, updated_atISO 8601UTC。
manage_urlurl代碼在儀表板中的頁面,用於「在 QRFLOW 中開啟」連結。
image_urlurlGET /codes/:id/image.svg。需要 Authorization 標頭;不是公開的圖片 URL。
svg_download_url, png_download_urlurl相同的 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

Webhooks

當有事件發生時,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當你按下「測試」時。webhook_id、message

收到的內容

每個 payload 都是 { 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>。使用你的密鑰對 ${t}.${rawBody} 計算 HMAC-SHA256,並以恆定時間比較 v1;如果 t 超過五分鐘,則拒絕。使用你收到的原始位元組,絕不要使用重新序列化的物件。可用的接收器範例位於 Next.js 和 Python 的食譜中,且兩個 SDK 都包含此輔助函式。

傳遞規則

  • 在 8 秒內回應任何 2xx 狀態碼。在回應後再做其他工作。
  • 任何其他狀態會在 1、5、15、60、240 和 720 分鐘後重試。
  • 連續二十次失敗會停用 webhook 並透過電子郵件通知帳戶擁有者。接收器修復後重新啟用;佇列中的重試會恢復。
  • URL 必須是公開主機上的 https。拒絕 localhost、私有範圍和 qrflow.codes 本身。開發時請使用隧道。
  • 按下 Test 以接收一個已簽章的 ping,並查看你的伺服器回應的狀態。

錯誤

每個錯誤都是 { "error": "<code>", "message": "<what to do>" },並帶有以下狀態碼。訊息是為人編寫的;請直接顯示。

狀態error說明

症狀、原因、修復

疑難排解

每次呼叫都出現 401 invalid_token

原因:標頭錯誤或金鑰未啟用。

修復:精確傳送 Authorization: Bearer qrf_live_…(一個空格,不是冒號)。檢查金鑰是否在 Account › API keys 中被撤銷。如果你是從聊天或文件複製的,請注意結尾的句點或智慧引號。

使用在 MCP 伺服器上有效的 token 呼叫 /api/v1 卻出現 401

原因:為 https://qrflow.codes/mcp 鑄造的 token 綁定於該服務。

修復:使用 API 金鑰進行 REST 呼叫,或執行第二次 OAuth 流程且不帶 resource= 以取得 REST API 的 token。

建立金鑰或 webhook 時出現 402 upgrade_required

原因:兩者都是 Business 功能。

修復:在 /pricing 升級,或使用 MCP 伺服器,它可透過登入在每個方案上運作。

從 OAuth 應用程式 POST /codes 時出現 402

原因:使用者的方案不包含應用程式要求的內容(動態代碼、網域)。

修復:先讀取 GET /me features 並調整:無論如何都建立代碼(在 Free 方案上它將是靜態的),或告知使用者方案需要什麼。

403 insufficient_scope

原因:建立金鑰時就固定了權限範圍。

修復:使用你需要的範圍建立新金鑰,並撤銷舊金鑰。對於 OAuth,請在授權請求中要求該範圍。

當我 PATCH destination_data 時出現 400 not_dynamic

原因:代碼是靜態的:在 Free 方案上建立,或是 Wi-Fi/vCard/text 類型。

修復:對於付費方案上的 url/phone/email/sms/location,POST /codes/:id/dynamic,然後重新下載並重新列印(圖片會改變)。Wi-Fi、vCard 和 text 永遠不能是動態的;改為建立一個開啟頁面的 url 代碼。

當我設定 slug 時出現 400 no_domain

原因:連結名稱位於你的網域上。

修復:先在 Account 頁面上連結並驗證網域。在 qrflow.codes/q 上,路徑永遠是 short_code。

slug 出現 409 conflict

原因:你的另一個代碼已使用該名稱。

修復:使用 GET /codes?q= 找到它,或選擇其他名稱。名稱是每個帳戶唯一的,不是全域的。

瀏覽器控制台出現 CORS 錯誤

原因:API 僅接受伺服器對伺服器的呼叫(以及 Canva)。這是刻意的:網頁中的金鑰就是洩漏的金鑰。

修復:將呼叫移至路由處理器、伺服器動作、邊緣函式或後端,並從頁面呼叫該處。

圖片顯示 QRFLOW 浮水印

原因:帳戶是 Free 方案。

修復:付費方案會移除它。Free 是為網站自己的產生器設計的。

我新增網域後 short_url 仍顯示 qrflow.codes/q/…

原因:網域尚未驗證,或其 CNAME 錯誤。

修復:檢查 Account 頁面或 GET /domains 的狀態(狀態必須是 verified)。一旦驗證,現有代碼會自動切換。

image_url 在 <img> 標籤中給出 401

原因:它需要 Authorization 標頭,而 <img> 無法傳送。

修復:使用同一個 Code 物件中的 svg_download_url 或 png_download_url:這些簽章連結在 24 小時內無需標頭即可使用。若要永久使用,請透過你的伺服器代理 image_url(參見 Next.js 食譜)或自行編碼 short_url。

我需要 PNG,而不是 SVG

原因:SVG 帶有邊框和標誌;PNG 是純代碼。

修復:GET /codes/:id/image.png(bearer 或簽章的 png_download_url)回傳 PNG,尺寸為 256 到 2048 像素。若要帶邊框的 PNG,請使用 sharp 或 resvg 轉換 SVG(sharp(svgBuffer).png().toBuffer())。

我的助手說圖片端點拒絕了它,並自己畫了代碼

原因:它抓取了需要 bearer 的 image_url。

修復:每個代碼現在都帶有 png_download_url 和 svg_download_url,且 get_qr_image 會回傳它們;助手可以在無需登入的情況下 curl 這些連結。本地繪製的、編碼相同 short_url 的代碼仍然有效且仍會計算掃描次數,但它缺少邊框和標誌。

Webhook 從未送達

原因:URL 規則或接收器問題。

修復:URL 必須是公開主機上的 https(不能是 localhost、私有 IP 或 qrflow.codes)。在 webhook 上按下 Test:結果會顯示你的伺服器回應的狀態。掃描事件是批次處理的,最多可能需要約五分鐘;來自儀表板的 code.* 事件也會排隊幾分鐘,而 API 和 MCP 寫入則會立即傳遞。

簽章永遠無法驗證

原因:你對重新序列化的 body 進行了簽章。 FixVerify 針對你收到的原始位元組進行驗證,時間點在 JSON 解析之前。在 Express 中,於該路由使用 express.raw({ type: 'application/json' });在 Next.js App Router 中,使用 await req.text();在 Flask 中,使用 request.get_data()。接著計算 ${t}.${raw}\ 的 HMAC-SHA256。

Webhook 自動關閉

原因連續二十次失敗。

修正修復接收端,然後重新將它設為啟用(帳戶 › Webhooks,或刪除後重新建立)。發生時系統已寄信通知你。排入佇列的重試會恢復。

重複的 webhook 傳遞

原因回應時間超過 8 秒的慢速 2xx 會被視為失敗並重試。

修正先回應,再處理。以 payload 的 id 進行去重,該 id 在重試期間保持穩定。

匯入期間出現 429 rate_limited

原因每個金鑰每分鐘 600 次請求。

修正改用 POST /codes/bulk(單一請求內含 2,000 個代碼),而非每個代碼一次 POST,或依 Retry-After 秒數暫停。

我刪除了一個代碼,印出的海報現在顯示「找不到代碼」

原因刪除是永久性的,且會使連結失效。

修正無法復原。下次請使用 PATCH { paused: true };暫停的代碼會顯示友善頁面,且可恢復。

降級後我的金鑰無法運作

原因金鑰在離開 Business 方案後仍可運作 30 天,之後回應 402。

修正重新訂閱;沒有任何資料被刪除,相同的金鑰會再次運作。

清單中沒有你要的項目?寄信至 hello@qrflow.codes,附上確切的請求與你收到的 JSON 錯誤。Business 帳戶享有優先處理。

限制與合理使用

限制
每個金鑰每分鐘請求數600。超過時回應 429 並附 Retry-After。
每個帳戶的金鑰數10
每個帳戶的 Webhook 數10
已儲存代碼(合理使用)Premium 1,000 個,Business 25,000 個;API 在兩倍數量時停止。
批次Premium 每月 500 個(每次請求 500 個);Business 每月 10,000 個(每次請求 2,000 個)。
連結網域Premium 1 個,Business 5 個
掃描次數無限制。Premium 每個代碼每月 100,000 次掃描、Business 1,000,000 次時會寄送檢查郵件;不會限制流量。
掃描分析視窗每次請求 92 天
清單頁面大小100(?limit=)
標籤/說明文字/代碼名稱120/60/40 個字元
Webhook 逾時與重試8 秒;重試間隔為 1、5、15、60、240 和 720 分鐘;連續 20 次失敗後關閉。
離開 Business 方案後金鑰和 Webhook 持續運作 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: 在建立時即被拒絕,因此受入侵的整合無法將你的代碼變成攻擊工具。
  • Webhook URL 必須是公開主機上的 https;QRFLOW 絕不會呼叫私人網路或自身。每次傳遞都有簽章,每個 payload 都有穩定的 id。
  • OAuth 用戶端以 PKCE S256 註冊,權杖綁定於簽發時的伺服器;用於 MCP 伺服器的權杖無法在 REST API 上重放。
  • 任何人都可在帳戶頁面撤銷金鑰或中斷應用程式連線;效果立即生效。

你方應做的事項

  • 使用環境變數,絕不寫入原始碼。若金鑰進入 git 歷史,請撤銷它。
  • 僅限伺服器端。API 拒絕瀏覽器來源,但你包裝它的端點也需要驗證,否則任何人都能使用你的帳單建立代碼。
  • 為每個整合建立獨立金鑰,並賦予所需權限範圍,以整合名稱命名。撤銷一個金鑰只會影響單一項目。
  • 驗證 webhook 簽章,並拒絕超過五分鐘的時間戳記。
  • 若使用者的資料會進入標籤或目的地,請記得 QRFLOW 會儲存它們;盡量不要在標籤中放入個人資料。

掃描記錄了什麼,以及不記錄什麼

  • 每次重新導向會儲存裝置類型、國家、城市、來源網站、瀏覽器、作業系統和語言(皆從請求推導),以及代碼+日期+IP+使用者代理的單向雜湊,供擁有者計算不重複訪客數。該雜湊無法還原為位址。
  • 不會在掃描者身上設定 cookie,IP 位址本身也不會與掃描記錄一同保留。已知的機器人與連結預覽爬蟲會被略過。
  • 刪除代碼會一併刪除其掃描記錄。刪除帳戶會刪除所有資料。
  • 全文:https://qrflow.codes/privacy 和 https://qrflow.codes/terms.

版本與穩定性

API 在路徑中標示版本:/api/v1。在 v1 內,我們只會新增欄位、端點、類型與事件;不會移除或重新命名任何項目,你的程式碼應忽略回應中的未知欄位。

若變更必須破壞 v1,會以 /api/v2 推出,且 v1 至少持續運作十二個月。金鑰擁有者會提前 90 天收到棄用通知郵件。

MCP 伺服器對其工具遵循相同規則:只會新增引數,每個工具名稱保持不變。

位於 /api/v1/openapi.json 的 OpenAPI 文件與 /llms-full.txt 的 Markdown 皆由提供 API 的程式碼產生,因此它們描述的是目前實際運作的內容。

開發者常見問題

使用 QRFLOW API 需要付費嗎?

API 金鑰隨 Business 方案提供,每月 29 美元,可逐月訂閱。MCP 伺服器(Claude、ChatGPT、Cursor、Claude Code)與供你自己應用程式使用的 OAuth 可透過登入在任何方案上運作,其可建立的內容依方案而定。GET /catalog、GET /frames 和 /preview.svg 完全不需要金鑰。

我可以透過 API 免費產生 QR 碼嗎?

使用金鑰不行。若只是單純的靜態圖片,qrflow.codes 的免費產生器或任何開源 QR 程式庫即可勝任。API 是為動態代碼、你自己的網域、分析、批次與 webhook 而設計,這些正是付費帳戶的用途。

我可以從瀏覽器呼叫 API 嗎?

不行。它拒絕瀏覽器來源,因此金鑰絕不會出現在網頁中。請從路由處理器、伺服器動作、邊緣函式或後端呼叫它,再從你的頁面呼叫那些端點。

我可以取得哪些圖片格式?

SVG(含你的顏色、外框、說明文字與標誌,GET /codes/:id/image.svg,名義尺寸 256 至 4096 px)與純 PNG(GET /codes/:id/image.png,256 至 2048 px)。兩者皆接受 bearer,或使用每個 Code 物件攜帶的簽章 svg_download_url/png_download_url,這些網址在 24 小時內無需標頭即可使用。MCP 工具 get_qr_image 會回傳內嵌 PNG 與兩個連結。

印出 QR 碼後還能變更嗎?

可以,前提是動態代碼(付費方案上的 url、phone、email、sms、location)。使用新的 destination_data 執行 PATCH /codes/:id;圖片不會改變,下一次掃描會前往新位置。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 為每個代碼選擇網域。連結名稱(slug)可在其上建立易讀路徑。

掃描會記錄掃描者的哪些資訊?

裝置類型、國家、城市、來源網站、瀏覽器、作業系統與語言(皆來自請求),加上用於不重複訪客計數的每日單向雜湊。不會設定 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 是位於 https://qrflow.codes/mcp. 的 MCP 伺服器。將它新增為連接器、登入一次,然後用一般文字提出需求。十一種工具涵蓋建立、編輯、暫停、命名、批次、分析、圖片與網域。

我自己的使用者可以將他們的 QRFLOW 帳戶連接到我的應用程式嗎?

可以,使用 OAuth 2.0。在 /api/oauth/register 註冊用戶端(無需帳戶),將使用者導向 /oauth/authorize 並搭配 PKCE,然後使用他們的權杖呼叫 API。代碼會建立在他們的帳戶中,並依其方案運作。

如何在 localhost 測試 webhook?

使用隧道(cloudflared 或 ngrok)公開你的開發伺服器,並將其 https 位址用作 webhook URL,然後在帳戶 › Webhooks 按下測試,以接收帶簽章的 ping。Webhook URL 必須是公開 https;localhost 與私人位址會被拒絕。

如果我取消 Business 方案,我的整合會怎樣?

金鑰與 webhook 持續運作 30 天,之後回應 402。代碼、掃描記錄與網域保留在帳戶中。重新訂閱會以相同金鑰恢復一切。

如何透過 API 建立 Google 評論、Instagram、Wi-Fi 或 PDF 代碼?

GET /catalog 會列出每種代碼類型及其欄位。接著以該類型的 type 與欄位執行 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.txthttps://qrflow.codes/llms-full.txt這份完整參考資料以 Markdown 格式呈現:概念、每個端點、每個 MCP 工具、範例、疑難排解、常見問題。由與此頁面相同的來源產生。
developers.mdhttps://qrflow.codes/developers.md相同文件,供擷取 .md 的工具使用。
llms.txthttps://qrflow.codes/llms.txt供助理使用的網站索引,指向此處。
單頁 API 說明https://qrflow.codes/qr-code-apiAPI 的功能、何時用戶端函式庫是更好的選擇,以及其成本。這是此參考資料的簡短版本,用於決策而非建置。
openapi.jsonhttps://qrflow.codes/api/v1/openapi.jsonOpenAPI 3.1。可匯入 Postman、Insomnia、程式碼產生器或 ChatGPT Action。
MCP 伺服器https://qrflow.codes/mcpStreamable HTTP,支援動態註冊的 OAuth 或作為 bearer 的 Business 金鑰。
server.jsonhttps://qrflow.codes/.well-known/mcp/server.jsonMCP 註冊清單。
OAuth 探索https://qrflow.codes/.well-known/oauth-authorization-serverRFC 8414 中繼資料;受保護資源文件位於其旁。
npm 套件https://www.npmjs.com/package/qrflownpm install qrflow。具型別用戶端、零依賴、webhook 驗證。Python 單一檔案用戶端位於 https://qrflow.codes/sdk/qrflow.py.
GitHubhttps://github.com/nativecodeapps/qrflow-sdk用戶端、OpenAPI 快照,以及適用於 Next.js、Workers、Express、FastAPI 和 Flask webhook 的可執行範例。歡迎提出 Issue 和 PR。

問題、想法、我們應新增的程式碼類型:hello@qrflow.codes。條款:/terms。隱私權:/privacy。