API de agregare
GET /v1/codes/:id/scans — serii temporale + top țări/dispozitive/sisteme de operare pentru un singur obiect cod.
Fiecare scanare a unui cod QR dinamic generează o înregistrare de scanare (Scan-Record) în spațiul tău de lucru (Workspace). Colectarea datelor se face în întregime la nivel de Cloudflare Edge — fără servicii externe de urmărire, fără cookie-uri și fără ca IP-ul original să ajungă vreodată în baza ta de date.
Trei moduri de a consuma datele de scanare:
API de agregare
GET /v1/codes/:id/scans — serii temporale + top țări/dispozitive/sisteme de operare pentru un singur obiect cod.
Webhook-uri (în timp real)
Evenimentul qr.scanned per scanare, semnat HMAC-SHA256. Vezi Webhook-uri.
Dashboard
Vizualizare în dashboard-ul qr3.app — nu este necesar niciun apel API.
Pentru fiecare scanare, se creează o înregistrare în tabelul scans:
| Câmp | Sursă | Exemplu |
|---|---|---|
id | UUID generat de server | scn_d1f8… |
code_id | ID-ul codului QR scanat | qr_a1b2c3d4 |
workspace_id | Workspace-ul codului | ws_xxx |
country | Cloudflare cf.country | AT |
region | Cloudflare cf.region | Vienna |
city | Cloudflare cf.city | Wien |
device_type | Analiză User-Agent | mobile, tablet, desktop |
os | Analiză User-Agent | iOS, Android, macOS, Windows |
browser | Analiză User-Agent | Safari, Chrome, Firefox |
referer | Header HTTP Referer | https://example.com/landing |
language | Header Accept-Language (prima limbă) | de |
redirected_to | Destinația reală de redirecționare | https://example.com |
ip_hash | SHA-256(IP + salt zilnic) — ireversibil | 8f3a… |
scanned_at | Timestamp ISO-8601 | 2026-05-12T14:32:11.000Z |
Toate datele geografice (country, region, city) provin din obiectul cf de la Cloudflare și se bazează pe baza de date Geo-IP a Cloudflare. Nu sunt interogate servicii externe de Geo-IP — rezoluția are loc în același Worker care execută și redirecționarea.
Acest lucru are trei consecințe:
city nu este întotdeauna disponibil (de exemplu, în cazul VPN-urilor, operatorilor de telefonie mobilă sau regiunilor mici). Așteaptă-te la valori null și ia-le în calcul în dashboard-urile tale.GET /v1/codes/:id/scansReturnează date analitice agregate pentru un singur cod QR pe o perioadă selectabilă.
curl "https://qr3.app/v1/codes/qr_a1b2c3d4/scans?days=30" \ -H "Authorization: Bearer qr3_sk_..."const analytics = await qr3.scans.get('qr_a1b2c3d4', { days: 30 });console.log(analytics.period_scans, analytics.top_countries);qr3 scans qr_a1b2c3d4 --days 30Parametri de interogare (Query Parameters):
| Parametru | Tip | Implicit | Descriere |
|---|---|---|---|
days | integer | 30 | Perioada în zile (1–365) |
Răspuns (HTTP 200):
{ "data": { "code_id": "qr_a1b2c3d4", "short_code": "r7f3Kx", "total_scans": 1842, "period_days": 30, "period_scans": 367, "scans_by_day": [ { "date": "2026-04-13", "count": 12 }, { "date": "2026-04-14", "count": 18 } ], "top_countries": [ { "value": "AT", "count": 142 }, { "value": "DE", "count": 98 }, { "value": "CH", "count": 41 } ], "top_devices": [ { "value": "mobile", "count": 281 }, { "value": "desktop", "count": 72 }, { "value": "tablet", "count": 14 } ], "top_os": [ { "value": "iOS", "count": 158 }, { "value": "Android", "count": 123 }, { "value": "macOS", "count": 48 } ] }, "meta": { "request_id": "req_xyz123" }}Câmpuri de răspuns:
| Câmp | Descriere |
|---|---|
total_scans | Numărul total de scanări pe întreaga durată de viață a codului (independent de intervalul days) |
period_scans | Numărul total de scanări în intervalul de timp selectat |
scans_by_day | Grupuri zilnice (buckets), în ordine crescătoare după dată, zilele fără scanări fiind omise |
top_countries | Top 8 țări în intervalul de timp selectat, în ordine descrescătoare |
top_devices | Top 5 tipuri de dispozitive (mobile, tablet, desktop) |
top_os | Top 5 sisteme de operare |
Totalurile la nivel de Workspace (de exemplu, scanările pe lună pentru toate codurile) sunt disponibile prin GET /v1/workspaces/:id în câmpul scans_this_month. Pentru analize comparative între coduri (cross-code), recomandăm dashboard-ul sau un export periodic.
Dacă dorești să procesezi evenimentele de scanare imediat ce se produc — de exemplu, pentru dashboard-uri live, urmărirea lead-urilor sau integrări CRM — abonează-te la evenimentul qr.scanned:
curl -X POST https://qr3.app/v1/webhooks \ -H "Authorization: Bearer qr3_sk_..." \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/webhooks/qr3", "events": ["qr.scanned"], "secret": "my-secret-key-min-16-chars" }'Payload:
{ "id": "evt_abc123xyz", "type": "qr.scanned", "created": "2026-05-12T14:32:11.000Z", "data": { "code_id": "qr_a1b2c3d4", "short_code": "r7f3Kx", "scan_id": "scn_d1f8...", "country": "AT", "device_type": "mobile", "os": "iOS" }}Documentația completă privind verificarea semnăturii, logica de reîncercare (retry) și jurnalele de livrare (delivery logs) se găsește în API → Webhooks.
Înregistrările de scanare (Scan-Records) nu conțin adrese IP cu caracter personal. IP-ul original este înlocuit în Worker-ul Edge printr-o funcție hash criptografică (SHA-256) cu un salt care se rotește zilnic. Acest lucru înseamnă:
Perioada de retenție depinde de abonament:
| Abonament | Retenție |
|---|---|
| Free | 7 zile |
| Pro | 90 de zile |
| Business / Agency | 1 an |
| Enterprise | Personalizat (SLA) |
Un job cron care rulează zilnic (purgeOldScans) elimină automat înregistrările mai vechi — câmpul total_scans de pe obiectul cod rămâne neafectat.
days=365), payload-ul poate ajunge la câțiva KB. Folosește cache pe partea de client cu un TTL scurt (de exemplu, 60 s).top_countries, top_devices, top_os sunt limitate pe partea de server la 8, respectiv 5 înregistrări. Pentru analize mai detaliate, exportă datele brute.null: Câmpurile country, region, city, referer, language pot fi null. Tratează aceste cazuri ca „Necunoscut” în analizele tale.