Abundera QR Pro API
pro.qr.abundera.ai의 REST API 레퍼런스. 동적 QR 코드를 프로그래밍 방식으로 생성, 수정, 분석할 수 있습니다. 모든 통신은 Bearer 토큰 인증을 사용한 HTTPS 기반 JSON입니다.
/docs/openapi.json, Postman, Insomnia, 또는 OpenAPI 3.1 클라이언트에 임포트하세요. 코드, 분석, 그룹, 팀, 웹훅, 사용자 등 36개 고객용 엔드포인트를 포함합니다. 관리자 및 Stripe 웹훅 엔드포인트는 서비스 간 전용으로 의도적으로 제외되었습니다.소개
Abundera QR Pro API를 사용하면 동적 QR 코드를 프로그래밍 방식으로 생성, 수정, 분석할 수 있습니다. 대시보드에서 자동화하고 싶은 모든 개발자 작업이 가능합니다. 팀 관리, 청구, 계정 흐름은 대시보드 UI에서 처리됩니다. 이 API는 개발자용 코드 작업에 범위가 제한됩니다.
기본 URL: https://pro.qr.abundera.ai/api
요청 형식: POST / PATCH / DELETE 시 JSON (Content-Type: application/json).
응답 형식: JSON (application/json; charset=utf-8).
사용 가능 여부: API 접근은 Business 이상 요금제 기능입니다. Solo 요금제는 대시보드만 사용 가능하며 API는 이용할 수 없습니다.
인증
모든 요청에는 API 키를 Bearer 토큰으로 포함해야 합니다:
Authorization: Bearer abnd_qrpro_.../account/keys에서 키를 생성하고 폐기할 수 있습니다 (Business, Team, Agency 요금제). 원본 abnd_qrpro_... 토큰은 생성 시 단 한 번만 표시됩니다. 즉시 저장하세요. 저장하는 것은 SHA-256 해시뿐이므로 분실한 키는 복구할 수 없습니다.
인증되지 않은 요청은 401 { "error": "not_signed_in" }을 반환합니다. 유효하지 않거나 폐기된 키는 401 { "error": "invalid_api_key" }를 반환합니다.
API 키는 생성한 사용자에게 범위가 지정됩니다. 해당 사용자가 팀의 멤버인 경우, 아래 엔드포인트는 팀 코드에서 자동으로 작동합니다 (현재 팀 컨텍스트는 사용자 계정에 저장되며 대시보드에서 관리됩니다).
요청 제한
API 키별로 적용됩니다. 모든 응답에는 X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (윈도우가 초기화되는 유닉스 초)가 포함됩니다.
| 요금제 | 제한 | 윈도우 |
|---|---|---|
| Business | 하루 1,000건 | UTC 일 |
| Team | 하루 10,000건 | UTC 일 |
| Agency | 하루 50,000건 | UTC 일 |
| Solo | (403 insufficient_plan) | , |
예산 초과 요청은 Retry-After 헤더(초 단위)와 함께 429 { "error": "rate_limited", "window": "day", "retry_at": 1234567890 }를 반환합니다.
스캔에는 요청 제한이 없습니다, 리디렉션 핫 경로(aqr.net/{shortcode})는 인증이 없고 스캔당 예산도 없습니다. 각 요금제에는 명시적인 월간 스캔 한도가 있습니다 (100만 / 100만 / 1,000만 / 3,000만). 한도를 초과해도 리디렉션은 계속 작동합니다. 업그레이드 또는 일시적 급증 여부를 결정할 수 있도록 이메일로 알려드립니다. 하루 약 1,000만 건 이상을 계획 중이라면 이메일로 문의해 용량을 조율하세요.
오류
모든 오류 응답은 머신 판독 가능한 error 코드와 관련 추가 컨텍스트가 포함된 JSON입니다:
{ "error": "plan_limit", "plan": "business", "limit": 500, "current": 500 }| 상태 | 코드 | 의미 |
|---|---|---|
| 400 | validation_error | 본문 필드 유효성 검사 실패. 응답에 field + message 포함. |
| 401 | not_signed_in / invalid_api_key | Bearer 토큰 없음, 유효하지 않음, 또는 폐기됨. |
| 402 | plan_limit | 요금제의 활성+일시정지 코드 한도 도달. 응답에 plan, limit, current 포함. |
| 402 | plan_expired | 90일 유예 기간 초과. 재개하려면 업그레이드 필요. |
| 403 | insufficient_plan | API 접근은 Business 이상 필요. Solo 사용자가 이 오류를 받습니다. |
| 403 | insufficient_role | 팀 역할에 요청된 변경 권한이 없습니다 (관리자 이상 필요). |
| 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" }생성된 shortcode와 인쇄할 short_url을 포함한 생성된 행과 함께 201을 반환합니다.
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}
소프트 삭제. grace_until = now + 90일로 status=grace로 전환됩니다. 리디렉션은 전체 유예 기간 동안 계속 작동합니다. 이것이 잠금 없는 가격 약속의 구체적 구현입니다. 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 키를 나열합니다. 원본 토큰은 반환되지 않으며 메타데이터만 반환됩니다.
{
"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, Cloudflare의CF-IPCountry헤더에서 얻은 ISO-3166-1 alpha-2. 도시, 지역, 지오IP 조회 없음.device_type, 짧은 User-Agent 정규식으로 분류된mobile/tablet/desktop/unknown. 원본 UA 문자열은 분류 직후 폐기됩니다.scan_count, 집계 카운터. 매 히트마다 upsert됩니다.
저장하지 않는 것: IP 주소 (해시 여부 불문), 원본 User-Agent 문자열, 도시 수준 지오, 일 미만 타임스탬프, 리퍼러, 쿠키, 리타겟팅 픽셀, 또는 개인 식별 벡터. 소규모 집계 재식별을 방지하기 위해 5 미만의 집계는 노이즈 플로어로 처리됩니다.
Team 및 Agency 요금제는 추가로 hour_bucket (YYYY-MM-DD-HH UTC)을 사용하는 병렬 시간별 집계를 기록합니다. 동일한 프라이버시 모델, 시간 미만 타임스탬프 없음, 동일한 노이즈 플로어, 개별 스캐너 데이터 없음.
전체 내용 읽기: 무료 도구 사이트의 /manifesto/와 /no-lock-in/.