Abundera QR Pro/ Documentation

Abundera QR Pro API

REST API-referentie voor pro.qr.abundera.ai. Maak, bewerk en analyseer dynamische QR-codes programmatisch. Alles is JSON over HTTPS, geverifieerd via bearer-token.

Laatst bijgewerkt: 2026-04-18 · support@abundera.ai · OpenAPI 3.1 spec (JSON) · Officiële SDK's (TS / Python / Go)

Machine-leesbare spec:/docs/openapi.json, importeer in Postman, Insomnia of een andere OpenAPI 3.1-client. Dekt 36 klantgerichte endpoints voor Codes, Analytics, Groups, Teams, Webhooks en User. Admin- en Stripe-webhook-endpoints zijn bewust uitgesloten (service-to-service alleen).

Inleiding

Met de Abundera QR Pro API maak, bewerk en analyseer je dynamische QR-codes programmatisch, alles wat een ontwikkelaar wil automatiseren vanuit het dashboard. Teambeheer, facturering en accountstromen blijven in de dashboard-UI; deze API is gericht op code-operaties op ontwikkelaarsniveau.

Basis-URL: https://pro.qr.abundera.ai/api

Verzoekformaat: JSON (Content-Type: application/json) bij POST / PATCH / DELETE.

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

Beschikbaarheid: API-toegang is een Business+-functie. Solo-abonnees kunnen het dashboard gebruiken, maar niet de API.

Authenticatie

Elk verzoek bevat een API-sleutel als bearer-token:

Authorization: Bearer abnd_qrpro_...

Maak sleutels aan bij /account/keys (Business, Team of Agency). De ruwe abnd_qrpro_...-token wordt precies één keer getoond bij aanmaken, sla hem direct op. Wij slaan alleen de SHA-256-hash op; een verloren sleutel is niet terug te halen.

Niet-geverifieerde verzoeken krijgen 401 { "error": "not_signed_in" }. Ongeldige of ingetrokken sleutels krijgen 401 { "error": "invalid_api_key" }.

API-sleutels zijn gekoppeld aan de gebruiker die ze heeft aangemaakt. Als die gebruiker lid is van een team, werken de onderstaande endpoints automatisch op de codes van dat team (de huidige teamcontext is opgeslagen op het gebruikersaccount en beheerd via het dashboard).

Limieten

Gehandhaafd per API-sleutel. Elk antwoord bevat X-RateLimit-Limit, X-RateLimit-Remaining en X-RateLimit-Reset (unix-seconden waarop het venster herstart).

AbonnementLimietVenster
Business1.000 verzoeken / dagUTC-dag
Team10.000 verzoeken / dagUTC-dag
Agency50.000 verzoeken / dagUTC-dag
Solo(403 insufficient_plan),

Verzoeken die het budget overschrijden, krijgen 429 { "error": "rate_limited", "window": "day", "retry_at": 1234567890 } met een Retry-After-header in seconden.

Scans zijn niet gelimiteerd, het redirect-pad (aqr.net/{shortcode}) vereist geen authenticatie en heeft geen scan-budget. Elk abonnement heeft een expliciet maandelijks scan-cap (100k / 1M / 10M / 30M). Overschrijd je het cap, dan blijft de redirect gewoon werken; wij sturen je een e-mail zodat je kunt beslissen of je wilt upgraden of de piek accepteert. Plannen boven ~10M dagelijkse scans? Mail ons om capaciteit af te stemmen.

Fouten

Elke foutrespons is JSON met een machine-leesbare error-code en, waar relevant, aanvullende context:

{ "error": "plan_limit", "plan": "business", "limit": 500, "current": 500 }
StatusCodeBetekenis
400validation_errorVeldinvoer mislukt validatie. Antwoord bevat field + message.
401not_signed_in / invalid_api_keyOntbrekende, ongeldige of ingetrokken bearer-token.
402plan_limitOp het code-cap van je abonnement. Antwoord bevat plan, limit, current.
402plan_expiredAccount is voorbij het 90-daagse respijtvenster; upgrade om te hervatten.
403insufficient_planAPI-toegang vereist Business of hoger. Solo-gebruikers raken dit.
403insufficient_roleJe teamrol staat de gevraagde mutatie niet toe (admin+ vereist).
404not_foundResource bestaat niet, of is niet zichtbaar in je scope.
409code_not_editableDe code heeft de status grace of expired; activeer opnieuw om te bewerken.
429rate_limitedPer-plan daily budget exceeded. See Limieten.
500internalOnverwerkte serverfout, mail support als het reproduceerbaar is.

Codes

Dynamische QR-codes: een 7-teken Base58-shortcode die omleidt via aqr.net/{shortcode}. Elke code heeft een statische reservekopie die je kunt downloaden via het dashboard, als je ooit stopt met betalen, werkt de statische versie nog steeds zonder onze redirect.

GET /api/codes

Geeft alle codes in je huidige scope (persoonlijk, of het team waaronder je nu werkt). Geeft een array terug met een 30-daagse scan-samenvatting 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 campagne", "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

Maak een nieuwe dynamische code aan. Het actieve+gepauzeerde code-cap van je abonnement wordt gecontroleerd vóór de invoeging. Minimale body:

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

Full customization (all optional):

{ "url":          "https://example.com/landing",
  "label":        "Voorjaarscampagne",
  "tags":         "q2,print",
  "qr_type":      "url",
  "style_json":   "{...}",
  "logo_key":     "instagram",
  "frame_style":  "scan-me",
  "frame_text":   "SCAN ME" }

Geeft 201 terug + de aangemaakte rij inclusief de gegenereerde shortcode en de short_url die je afdrukt.

GET /api/codes/{id}

Haal een enkele code op. 404 als niet in je scope.

PATCH /api/codes/{id}

Werk een muteerbaar veld bij. Meest voorkomend: wijzig de bestemmings-URL van een al afgedrukte code.

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

Wijzigingen verspreiden zich binnen seconden naar de redirect. Geldige status-waarden voor PATCH: "active", "paused". Gebruik DELETE om te verwijderen.

DELETE /api/codes/{id}

Zachte verwijdering. Zet over naar status=grace met grace_until = nu + 90 dagen. De redirect blijft werken tijdens het volledige respijtvenster, dit is de no-lock-in prijsbelofte in de praktijk. Na 90 dagen wordt de code expired en geeft de redirect 410 Gone terug.

POST /api/codes/import

Bulk aanmaken via een array-payload (ook gebruikt door de "Opslaan in Pro"-stroom op qr.abundera.ai). Accepteert een enkele of een reeks code-payloads. Het abonnementslimiet wordt één keer gecontroleerd vóór de batch.

Analytics

GET /api/codes/{id}/analytics

Query-parameters:

  • range=7d|30d|90d|1y|3y, beperkt tot de retentie van je abonnement (Solo 1j, Business 2j, Team/Agency 3j).
  • granularity=day|hour, uurlijks is alleen voor Team en Agency; maximaal 7-daags venster voor uurlijks.
{
  "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 }
  ]
}

Countries with fewer than 5 scans in the window are folded into "Other" for privacy (see Privacymodel).

API-sleutels

Maak en trek sleutels in via de /account/keys-dashboardpagina. Programmatisch zelfbeheer is alleen-lezen via de API, je kunt je sleutels opvragen en intrekken, maar voor het aanmaken van een nieuwe sleutel heb je het dashboard nodig.

GET /api/keys

Geeft je API-sleutels weer. Geeft nooit de ruwe token terug, alleen metagegevens.

{
  "keys": [
    { "id": "uuid", "label": "Productieserver",
      "created_at": 1713288000, "last_used_at": 1713370000 }
  ],
  "allowed": true,
  "plan": "business"
}

DELETE /api/keys/{id}

Intrekken. De sleutel werkt onmiddellijk niet meer; elk verzoek dat hem draagt, geeft daarna 401 invalid_api_key terug.

Data-export

GET /api/user/export

Download een ZIP met je volledige dataset, codes.csv (alle codes, inclusief grace + expired), scans.csv (samengevoegde dagelijkse rollup) en een README.txt die het formaat uitlegt. Het archief wordt opgeleverd als application/zip; sla het op in een bestand:

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

Importeer overal opnieuw. Dit is de portable-formaat-garantie, vendor lock-in is onmogelijk als je je eigen data bezit.

Privacymodel

Het scan-aggregaat is het volledige privacyverhaal. Wat we per scan opslaan op het redirect-hotpad:

  • code_id, welke van je codes werd gescand
  • day_bucket, UTC-datum (YYYY-MM-DD). Geen sub-dag precisie in het samengevoegde resultaat.
  • country, ISO-3166-1 alpha-2 van Cloudflare's CF-IPCountry-header. Geen stad, geen regio, geen geo-IP-lookup.
  • device_type, mobile / tablet / desktop / unknown, geclassificeerd via een korte User-Agent-regex. De ruwe UA-string wordt weggegooid bij classificatie.
  • scan_count, samengevoegde teller, geüpsert bij elke hit.

Wat we niet opslaan: IP-adressen (gehasht of anderszins), ruwe User-Agent-strings, stadsgeografie, sub-dag tijdstempels, referer, cookies, retargeting-pixels of enige individuele identificatievector. Een ruisdrempel van 5 onderdrukt heridentificatie bij kleine aggregaten.

Team- en Agency-abonnementen schrijven daarnaast een parallel uurlijks aggregaat met hour_bucket (YYYY-MM-DD-HH UTC). Hetzelfde privacymodel, geen fijnere tijdstempels dan uur, dezelfde ruisdrempel, hetzelfde gebrek aan individuele scannergegevens.

Lees het volledige verhaal: /manifesto/ en /no-lock-in/ op de gratis-tool-site.