Abundera QR Pro API
REST API 参考文档,服务于 pro.qr.abundera.ai。通过程序化方式创建、编辑和分析动态 QR 码。所有内容均为 JSON over HTTPS,通过 bearer token 认证。
/docs/openapi.json, 可导入 Postman、Insomnia 或任何 OpenAPI 3.1 客户端。涵盖 36 个面向客户的端点,包括 Codes、Analytics、Groups、Teams、Webhooks 和 User。Admin + Stripe webhook 端点已被有意排除(仅用于服务间调用)。简介
Abundera QR Pro API 让你以程序化方式创建、编辑和分析动态 QR 码, , 开发者在 控制台 中能做的一切自动化操作都可以通过 API 完成。团队管理、账单和账户流程保留在控制台 UI 中;此 API 的范围限于开发者级别的码操作。
Base URL: https://pro.qr.abundera.ai/api
请求格式: JSON(Content-Type: application/json),用于 POST / PATCH / DELETE。
响应格式: JSON(application/json; charset=utf-8)。
可用性: API 访问是 Business+ 功能。Solo 套餐只能使用控制台,无法访问 API。
认证
每个请求都需携带 API 密钥作为 bearer token:
Authorization: Bearer abnd_qrpro_...在 /account/keys(Business、Team 或 Agency 套餐)创建和撤销密钥。原始 abnd_qrpro_... token 仅在创建时显示一次, , 请立即存储。我们只存储其 SHA-256 哈希;丢失后无法恢复。
未认证请求返回 401 { "error": "not_signed_in" }。无效或已撤销的密钥返回 401 { "error": "invalid_api_key" }。
API 密钥归属于创建它的用户。如果该用户是某个团队的成员,以下端点会自动在该团队的码范围内操作(当前团队上下文存储在用户账户上,通过控制台管理)。
限速
按 API 密钥执行。每个响应都携带 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset(窗口重置时的 Unix 秒数)。
| 套餐 | 限制 | 窗口 |
|---|---|---|
| Business | 1,000 次请求/天 | UTC 天 |
| Team | 10,000 次请求/天 | UTC 天 |
| Agency | 50,000 次请求/天 | UTC 天 |
| Solo | (403 insufficient_plan) | , |
超出预算的请求返回 429 { "error": "rate_limited", "window": "day", "retry_at": 1234567890 },并附带以秒为单位的 Retry-After 响应头。
扫描不受限速限制, , 重定向热路径(aqr.net/{shortcode})无需认证,也无每次扫描预算。每个套餐有明确的月扫描上限(10 万 / 100 万 / 1000 万 / 3000 万)。超出上限后重定向仍会生效;我们会发邮件告知你,由你决定是升级还是等待一次性峰值过去。预计每日扫描量超过约 1000 万?联系我们提前协调容量。
错误
每个错误响应均为 JSON,包含机器可读的 error 代码,并在相关时提供额外上下文:
{ "error": "plan_limit", "plan": "business", "limit": 500, "current": 500 }| 状态码 | 代码 | 含义 |
|---|---|---|
| 400 | validation_error | 请求体字段未通过验证。响应包含 field + message。 |
| 401 | not_signed_in / invalid_api_key | 缺少、无效或已撤销的 bearer token。 |
| 402 | plan_limit | 已达到套餐的活跃+暂停码上限。响应包含 plan、limit、current。 |
| 402 | plan_expired | 账户已超过 90 天宽限期;请升级以恢复。 |
| 403 | insufficient_plan | API 访问需要 Business 或更高套餐。Solo 用户会遇到此错误。 |
| 403 | insufficient_role | 你的团队角色不允许执行所请求的修改(需要 admin+)。 |
| 404 | not_found | 资源不存在,或在你的权限范围内不可见。 |
| 409 | code_not_editable | 码处于宽限或过期状态;请重新激活后编辑。 |
| 429 | rate_limited | 超出套餐每日预算。参见 限速。 |
| 500 | internal | 未处理的服务器错误, , 如可复现,请发邮件给支持团队。 |
码
动态 QR 码:一个通过 aqr.net/{shortcode} 重定向的 7 位 Base58 短码。每个码都带有静态备用 QR,可从控制台下载, , 即使你停止付费,静态版本仍可正常解析,无需经过我们的重定向。
GET /api/codes
列出当前权限范围内的所有码(个人或你当前所在的团队)。返回数组,每个码附带 30 天扫描汇总。
$ curl -H "Authorization: Bearer abnd_qrpro_..." https://pro.qr.abundera.ai/api/codes
{
"codes": [
{ "id": "uuid", "shortcode": "aBc123x",
"url": "https://example.com/landing",
"label": "Q2 campaign", "tags": "q2,print",
"status": "active", "scans_30d": 1245,
"created_at": 1713288000, "updated_at": 1713370000 }
],
"plan": "business",
"plan_limit": 500,
"scope": { "type": "user" }
}POST /api/codes
创建一个新的动态码。在插入前会检查套餐的活跃+暂停码上限。最简请求体:
{ "url": "https://example.com/landing" }完整自定义(均为可选):
{ "url": "https://example.com/landing",
"label": "Spring campaign",
"tags": "q2,print",
"qr_type": "url",
"style_json": "{...}",
"logo_key": "instagram",
"frame_style": "scan-me",
"frame_text": "SCAN ME" }返回 201 + 创建的行,包含生成的 shortcode 和用于印刷的 short_url。
GET /api/codes/{id}
获取单个码。不在你的权限范围内时返回 404。
PATCH /api/codes/{id}
更新任意可变字段。最常见的用途:更改已印刷码的目标 URL。
$ curl -X PATCH -H "Authorization: Bearer abnd_qrpro_..." -H "Content-Type: application/json" -d '{"url":"https://example.com/new-landing"}' https://pro.qr.abundera.ai/api/codes/uuid更改会在数秒内传播到重定向。PATCH 的有效 status 值:"active"、"paused"。删除请使用 DELETE。
DELETE /api/codes/{id}
软删除。转为 status=grace,grace_until = now + 90 天。重定向在整个宽限窗口内保持正常工作, , 这是无绑定定价承诺的具体体现。90 天后码变为 expired,重定向返回 410 Gone。
POST /api/codes/import
从数组载荷批量创建(也用于 qr.abundera.ai 的"保存到 Pro"流程)。接受单个码载荷或数组。在批处理前统一检查套餐限制。
分析
GET /api/codes/{id}/analytics
查询参数:
range=7d|30d|90d|1y|3y, 受套餐数据保留期限制(Solo 1 年,Business 2 年,Team/Agency 3 年)。granularity=day|hour, 小时级仅限 Team 和 Agency;小时模式最多 7 天窗口。
{
"range": "30d", "days": 30, "granularity": "day",
"total": 4321,
"timeseries": [
{ "bucket": "2026-04-01", "scans": 142 },
{ "bucket": "2026-04-02", "scans": 178 },
...
],
"by_country": [
{ "key": "US", "total": 3012 },
{ "key": "CA", "total": 402 },
{ "key": "Other", "total": 108 }
],
"by_device": [
{ "key": "mobile", "total": 3850 },
{ "key": "tablet", "total": 312 },
{ "key": "desktop", "total": 159 }
]
}在所选窗口内扫描次数少于 5 次的国家会被归入 "Other",以保护隐私(参见 隐私模型)。
API 密钥
在 /account/keys 控制台页面创建和撤销密钥。API 对密钥的程序化自管理为只读, , 你可以列出和撤销密钥,但创建新密钥需要通过控制台(先有鸡还是先有蛋:你需要一个密钥来创建密钥)。
GET /api/keys
列出你的 API 密钥。从不返回原始 token, , 仅返回元数据。
{
"keys": [
{ "id": "uuid", "label": "Production server",
"created_at": 1713288000, "last_used_at": 1713370000 }
],
"allowed": true,
"plan": "business"
}DELETE /api/keys/{id}
撤销。密钥立即失效;此后任何携带该密钥的请求都返回 401 invalid_api_key。
数据导出
GET /api/user/export
下载包含完整数据集的 ZIP, , codes.csv(所有码,包括宽限期和过期码)、scans.csv(每日汇总数据)和一个说明格式的 README.txt。归档以 application/zip 格式输出;通过管道输出到文件:
$ curl -H "Authorization: Bearer abnd_qrpro_..." -o abundera-qr-export.zip https://pro.qr.abundera.ai/api/user/export可随时重新导入。这是可移植格式的保证, , 拥有自己的数据就不存在供应商锁定。
隐私模型
扫描聚合数据就是全部隐私内容。我们在重定向热路径上对每次扫描存储的内容:
code_id, 被扫描的是你的哪个码day_bucket, UTC 日期(YYYY-MM-DD)。返回给你的聚合数据无亚日精度。country, 来自 CloudflareCF-IPCountry头的 ISO-3166-1 alpha-2 代码。无城市、无地区、无 geo-IP 查询。device_type,mobile/tablet/desktop/unknown,通过简短的 User-Agent 正则表达式分类。原始 UA 字符串在分类后立即丢弃。scan_count, 聚合计数器,每次访问时 upsert。
我们不存储的内容:IP 地址(无论是否哈希)、原始 User-Agent 字符串、城市级地理位置、亚日时间戳、来源页面、Cookie、再营销像素,以及任何可识别个人身份的向量。噪音下限为 5,以抑制小样本的再识别风险。
Team 和 Agency 套餐还会写入一个包含 hour_bucket(YYYY-MM-DD-HH UTC)的并行小时聚合。隐私模型相同, , 无亚小时时间戳,相同噪音下限,同样不存储个人扫描数据。
了解完整内容:免费工具站点上的 /manifesto/ 和 /no-lock-in/。