Abundera QR Pro/ Documentation

Abundera QR Pro API

pro.qr.abundera.ai의 REST API 레퍼런스. 동적 QR 코드를 프로그래밍 방식으로 생성, 수정, 분석할 수 있습니다. 모든 통신은 Bearer 토큰 인증을 사용한 HTTPS 기반 JSON입니다.

최종 업데이트: 2026-04-18 · support@abundera.ai · OpenAPI 3.1 스펙 (JSON) · 공식 SDK (TS / Python / Go)

머신 판독 가능 스펙:/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 }
상태코드의미
400validation_error본문 필드 유효성 검사 실패. 응답에 field + message 포함.
401not_signed_in / invalid_api_keyBearer 토큰 없음, 유효하지 않음, 또는 폐기됨.
402plan_limit요금제의 활성+일시정지 코드 한도 도달. 응답에 plan, limit, current 포함.
402plan_expired90일 유예 기간 초과. 재개하려면 업그레이드 필요.
403insufficient_planAPI 접근은 Business 이상 필요. Solo 사용자가 이 오류를 받습니다.
403insufficient_role팀 역할에 요청된 변경 권한이 없습니다 (관리자 이상 필요).
404not_found리소스가 존재하지 않거나 범위 내에서 보이지 않습니다.
409code_not_editable코드가 유예 또는 만료 상태입니다. 편집하려면 재활성화하세요.
429rate_limited요금제별 일일 예산 초과. 요청 제한 참조.
500internal처리되지 않은 서버 오류, 재현 가능하면 지원팀에 이메일 문의.

코드

동적 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/.