API за агрегиране
GET /v1/codes/:id/scans — времеви редове + топ държави/устройства/операционни системи за единичен обект на код.
Всяко сканиране на динамичен QR-код генерира запис за сканиране (Scan-Record) във вашия Workspace. Събирането на данни се извършва изцяло на Cloudflare-Edge — без външни услуги за проследяване, без бисквитки (cookies) и без оригиналният IP адрес изобщо да достига до вашата база данни.
Три начина за консумиране на данните от сканиранията:
API за агрегиране
GET /v1/codes/:id/scans — времеви редове + топ държави/устройства/операционни системи за единичен обект на код.
Webhooks (в реално време)
Събитие qr.scanned за всяко сканиране, подписано с HMAC-SHA256. Вижте Webhooks.
Табло за управление
Визуализация в таблото на qr3.app — не е необходимо API повикване.
За всяко сканиране се създава запис в таблицата scans:
| Поле | Източник | Пример |
|---|---|---|
id | Генериран от сървъра UUID | scn_d1f8… |
code_id | Идентификатор на сканирания QR-код | qr_a1b2c3d4 |
workspace_id | Workspace на кода | ws_xxx |
country | Cloudflare cf.country | AT |
region | Cloudflare cf.region | Vienna |
city | Cloudflare cf.city | Wien |
device_type | Парсване на User-Agent | mobile, tablet, desktop |
os | Парсване на User-Agent | iOS, Android, macOS, Windows |
browser | Парсване на User-Agent | Safari, Chrome, Firefox |
referer | HTTP Referer заглавие | https://example.com/landing |
language | Accept-Language заглавие (първи език) | de |
redirected_to | Действителна цел на пренасочването | https://example.com |
ip_hash | SHA-256(IP + ежедневен salt) — необратим | 8f3a… |
scanned_at | ISO-8601 времево клеймо | 2026-05-12T14:32:11.000Z |
Всички географски данни (country, region, city) идват от обекта cf на Cloudflare и се базират на базата данни за Geo-IP на Cloudflare. Не се изпращат запитвания към външни Geo-IP услуги — разпознаването се случва в същия Worker, който извършва и пренасочването.
Това има три последствия:
city невинаги е налична (напр. при VPN, мобилни оператори или малки региони). Очаквайте стойности null и ги предвидете във вашите табла за управление.GET /v1/codes/:id/scansПредоставя агрегирани анализи за единичен QR-код за избран период от време.
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 30Параметри на заявката (Query Parameters):
| Параметър | Тип | По подразбиране | Описание |
|---|---|---|---|
days | integer | 30 | Период в дни (1–365) |
Отговор (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" }}Полета в отговора:
| Поле | Описание |
|---|---|
total_scans | Общ брой сканирания на кода за целия му период на съществуване (независимо от прозореца days) |
period_scans | Сума на сканиранията в избрания времеви прозорец |
scans_by_day | Дневни групи (buckets), възходящо по дата, дните без сканирания се пропускат |
top_countries | Топ 8 държави в избрания времеви прозорец, низходящо |
top_devices | Топ 5 типа устройства (mobile, tablet, desktop) |
top_os | Топ 5 операционни системи |
Общите суми за целия Workspace (напр. сканирания на месец за всички кодове) са налични чрез GET /v1/workspaces/:id в полето scans_this_month. За анализи на ниво различни кодове препоръчваме таблото за управление или периодичен експорт.
Ако искате да обработвате събитията от сканиранията в момента на тяхното възникване — например за табла за управление на живо, проследяване на потенциални клиенти (lead tracking) или CRM интеграции — абонирайте се за събитието 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" }}Пълна документация за верификация на подписи, логика за повторни опити (retry) и логове за доставка можете да намерите в API → Webhooks.
Записите за сканиране не съдържат лични IP адреси. Оригиналният IP адрес се заменя в Edge-Worker чрез криптографска хеш функция (SHA-256) с ежедневно ротиращ salt. Това означава:
Периодът на съхранение (Retention) зависи от плана:
| План | Съхранение |
|---|---|
| Free | 7 дни |
| Pro | 90 дни |
| Business / Agency | 1 година |
| Enterprise | По договаряне (SLA) |
Ежедневно изпълняваща се автоматична задача (cron job) purgeOldScans премахва по-старите записи автоматично — стойността на total_scans в обекта на кода остава непроменена.
days=365) обемът на данните може да достигне няколко KB. Кеширайте от страна на клиента с кратко време на живот (напр. TTL от 60 секунди).top_countries, top_devices, top_os са ограничени от страна на сървъра съответно до 8 или 5 записа. За по-задълбочени анализи експортирайте суровите данни.null: Стойностите за country, region, city, referer, language могат да бъдат null. Третирайте ги като „Неизвестно“ във вашите анализи.