Abundera QR Pro/ Documentation

Abundera QR Pro API

REST Rujukan API for pro.qr.abundera.ai. Create, edit, and analyze dinamik QR codes programmatically. Everything is JSON over HTTPS, authenticated via token bearer.

Kemas kini terakhir: 2026-04-18 · support@abundera.ai · OpenAPI 3.1 spec (JSON) · Official SDKs (TS / Python / Go)

Machine-readable spec:/docs/openapi.json, import into Postman, Insomnia, or any OpenAPI 3.1 client. Covers 36 customer-facing titik akhirs across Codes, Analytics, Groups, Teams, Webhook, and User. Admin + Stripe-webhook titik akhirs are intentionally excluded (service-to-service only).

Pengenalan

The Abundera QR Pro API lets you create, edit, and analyze dinamik QR codes programmatically, everything a dev wants to automate from the dashboard. Pengurusan pasukan, billing, and account flows stay in the dashboard UI; this API is skopd to developer-grade code operations.

Base URL: https://pro.qr.abundera.ai/api

Permintaan format: JSON (Content-Jenis: application/json) on POST / PATCH / DELETE.

Respons format: JSON (application/json; charset=utf-8).

Availability: API access is a Business+ feature. Solo pelans can use the dashboard but not the API.

Pengesahan

Every request carries an kunci API as a token bearer:

Authorization: Bearer abnd_qrpro_...

Create and batal kuncis at /account/kuncis (Business, Team, or Agency tier). The raw abnd_qrpro_... token is shown exactly once at creation, store it immediately. We store only its SHA-256 cincang; there is no way to recover a lost kunci.

Unauthenticated requests return 401 { "ralat": "not_tandaed_in" }. Insah or batald kuncis return 401 { "ralat": "tidak sah_api_kunci" }.

kunci APIs are skopd to the user who dicipta them. If that user is a ahli of a pasukan, the titik akhirs below operate on the pasukan's codes automatically (current-pasukan context is stored on the user account and managed via the dashboard).

Had kadar

Enforced per kunci API. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (unix seconds when the window rolls over).

PlanLimitWindow
Business1,000 requests / dayUTC day
Team10,000 requests / dayUTC day
Agency50,000 requests / dayUTC day
Solo(403 insufficient_pelan),

Over-budget requests return 429 { "ralat": "rate_limited", "window": "day", "cuba semula_at": 1234567890 } with a Retry-After pengepala in seconds.

Scans are not rate-limited, the ubah hala hot path (aqr.net/{shortcode}) has no auth and no per-imbas budget. Each pelan has an explicit monthly imbas cap (100k / 1M / 10M / 30M). Exceed the cap and the ubah hala still resolves; we email you so you can decide whether to naik taraf or ride out a one-off spike. Planning over ~10M daily imbass? Email us to coordinate capacity.

Ralat

Every ralat response is JSON with a machine-readable ralat code and, where relevant, additional context:

{ "ralat": "pelan_limit", "pelan": "business", "limit": 500, "current": 500 }
StatusCodeMeaning
400pengesahan_ralatBody field failed pengesahan. Respons includes field + message.
401not_tandaed_in / tidak sah_api_kunciMissing, tidak sah, or batald token bearer.
402pelan_limitAt your pelan's aktif+dijeda code cap. Respons includes pelan, limit, current.
402pelan_expiredAccount is past the 90-day grace window; naik taraf to resume.
403insufficient_pelanAPI access requires Business or higher. Solo users hit this.
403insufficient_perananYour pasukan peranan doesn't allow the requested mutation (pentadbir+ required).
404not_foundResource doesn't exist, or isn't visible to your skop.
409code_not_editableThe code is in grace or expired status; reactivate to edit.
429rate_limitedPer-pelan daily budget exceeded. See Had kadar.
500internalUnhandled server ralat, email support if reproducible.

Codes

Dynamic QR codes: a 7-char Base58 shortcode that ubah halas through aqr.net/{shortcode}. Every code carries a statik-sandaran QR you can download from the dashboard, if you ever stop paying, the statik version still resolves without touching our ubah hala.

GET /api/codes

List all codes in your current skop (personal, or the pasukan you're currently acting under). Pulangan an array with a 30-day imbas rollup per code.

$ 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", "tag": "q2,print",
      "status": "aktif", "imbass_30d": 1245,
      "dicipta_at": 1713288000, "dikemas kini_at": 1713370000 }
  ],
  "pelan": "business",
  "pelan_limit": 500,
  "skop": { "type": "user" }
}

POST /api/codes

Create a new dinamik code. Your pelan's aktif+dijeda code cap is checked before insert. Minimal body:

{ "url": "https://example.com/landing" }

Full customization (all optional):

{ "url":          "https://example.com/landing",
  "label":        "Spring campaign",
  "tag":         "q2,print",
  "qr_type":      "url",
  "style_json":   "{...}",
  "logo_kunci":     "instagram",
  "frame_style":  "imbas-me",
  "frame_text":   "SCAN ME" }

Pulangan 201 + the dicipta row including the generated shortcode and the short_url you print.

GET /api/codes/{id}

Fetch a single code. 404 if not in your skop.

PATCH /api/codes/{id}

Update any mutable field. The most common use: change the destinasi URL of an already-printed code.

$ curl -X PATCH \
       -H "Authorization: Bearer abnd_qrpro_..." \
       -H "Content-Jenis: application/json" \
       -d '{"url":"https://example.com/new-landing"}' \
       https://pro.qr.abundera.ai/api/codes/uuid

Changes propagate to the ubah hala within seconds. Valid status values for PATCH: "aktif", "dijeda". To padam, use DELETE.

DELETE /api/codes/{id}

Soft-padam. Transitions to status=grace with grace_until = now + 90 days. The ubah hala keeps working for the full grace window, this is the no-lock-in pricing promise made concrete. After 90 days the code becomes expired and the ubah hala returns 410 Gone.

POST /api/codes/import

Bulk-create from an array muatan (also used by the "Save to Pro" flow on qr.abundera.ai). Accepts a single code muatan or an array. Plan limit is enforced once before the batch.

Analytics

GET /api/codes/{id}/analitik

Query params:

  • range=7d|30d|90d|1y|3y, capped to your pelan's retention (Solo 1y, Business 2y, Team/Agency 3y).
  • granularity=day|hour, hourly is Team and Agency only; max 7-day window for hourly.
{
  "range": "30d", "days": 30, "granularity": "day",
  "total": 4321,
  "timeseries": [
    { "bucket": "2026-04-01", "imbass": 142 },
    { "bucket": "2026-04-02", "imbass": 178 },
    ...
  ],
  "by_negara": [
    { "kunci": "US", "total": 3012 },
    { "kunci": "CA", "total": 402 },
    { "kunci": "Other", "total": 108 }
  ],
  "by_peranti":  [
    { "kunci": "mudah alih",  "total": 3850 },
    { "kunci": "tablet",  "total": 312 },
    { "kunci": "desktop", "total": 159 }
  ]
}

Countries with fewer than 5 imbass in the window are folded into "Other" for privacy (see Privacy model).

kunci APIs

Create and batal kuncis from the /account/kuncis dashboard page. Programmatic self-management is read-only via the API, you can list your kuncis and batal them, but creating a new kunci requires the dashboard (chicken-and-egg: you'd need a kunci to create a kunci).

GET /api/kuncis

List your kunci APIs. Never returns the raw token, only metadata.

{
  "kuncis": [
    { "id": "uuid", "label": "Production server",
      "dicipta_at": 1713288000, "last_used_at": 1713370000 }
  ],
  "allowed": true,
  "pelan": "business"
}

DELETE /api/kuncis/{id}

Revoke. The kunci stops working immediately; any request bearing it returns 401 tidak sah_api_kunci thereafter.

Data eksport

GET /api/user/eksport

Download a ZIP containing your full dataset, codes.csv (every code, including grace + expired), imbass.csv (aggregated daily rollup), and a README.txt explaining the format. The arkib is emitted as application/zip; pipe it to a file:

$ curl -H "Authorization: Bearer abnd_qrpro_..." \
       -o abundera-qr-eksport.zip \
       https://pro.qr.abundera.ai/api/user/eksport

Re-import anywhere. This is the portable-format guarantee, no vendor lock-in is possible if you own your data.

Privacy model

The imbas aggregate is the whole privacy story. What we store per imbas on the ubah hala hot path:

  • code_id, which of your codes was diimbas
  • day_bucket, UTC date (YYYY-MM-DD). No sub-day precision on the aggregate returned to you.
  • negara, ISO-3166-1 alpha-2 from Cloudflare's CF-IPCountry pengepala. No city, no region, no geo-IP lookup.
  • peranti_type, mudah alih / tablet / desktop / unknown, classified from a short User-Agent regex. The raw UA string is discarded at classification time.
  • imbas_count, aggregate counter, upserted on every hit.

What we do not store: IP addresses (cincanged or otherwise), raw User-Agent strings, city-level geo, sub-day timestamps, referer, cookies, retargeting pixels, or any individual-identifying vector. A noise floor of 5 suppresses small-aggregate re-identification.

Team and Agency tiers additionally write a parallel hourly aggregate with hour_bucket (YYYY-MM-DD-HH UTC). Same privacy model, no finer-than-hour timestamps, same noise floor, same absence of individual-imbasner data.

Read the full story: /manifesto/ and /no-lock-in/ on the free-tool site.