Analytics and QR codes

All paths below are relative to https://api-v1.zingasuite.com/papi/v1.

Click and scan statistics

GET /links/{id}/stats?days=30

days is 1–365 and defaults to 30.

curl "https://api-v1.zingasuite.com/papi/v1/links/<id>/stats?days=7" \
  -H "Authorization: Bearer zk_live_xxx"
{
  "window_days": 7,
  "totals": {
    "clicks": 412,
    "scans": 96,
    "unique": 388,
    "all_time_clicks": 5210,
    "last_click_at": "2026-08-17T09:58:11Z"
  },
  "timeline": [
    { "date": "2026-08-11", "clicks": 48, "scans": 9 },
    { "date": "2026-08-12", "clicks": 71, "scans": 14 }
  ],
  "referrers": [{ "label": "mail.google.com", "count": 180 }],
  "devices":   [{ "label": "Mobile", "count": 291 }],
  "countries": [{ "label": "IN", "count": 204 }],
  "identity": {
    "known_clicks": 133,
    "known_recipients": 118,
    "anonymous_clicks": 375,
    "unlocked": true,
    "requires": null,
    "recipients": [
      {
        "contact_id": "…",
        "name": "Sam Lee",
        "email": "sam@example.com",
        "phone": "+14155551234",
        "clicks": 3,
        "first_click_at": "2026-08-12T07:41:02Z",
        "last_click_at": "2026-08-14T18:22:40Z"
      }
    ]
  }
}

Notes on the numbers:

  • Clicks and scans are counted separately, so you can attribute traffic to the
    emailed link versus the printed QR.
  • unique is derived from a hashed address, not a cookie — treat it as an
    approximation, not a person count.
  • all_time_clicks is the link's lifetime counter and ignores the window.
  • Breakdowns are top-8 buckets. Referrers are reduced to the host, and traffic
    with no referrer is grouped as Direct / unknown.
  • Bot hits are excluded. Mail-security scanners and image proxies are
    recognised at ingest and never move a counter.

The identity block

identity answers "who clicked", not just how many. Identity is only knowable
for clicks carrying a per-recipient marker — links ZingaConnect sent to a known
contact. Anything shared publicly or scanned from print is anonymous.

unlocked is false without a paid ZingaConnect plan; the counts are still
accurate, but recipients comes back empty and requires names what would
unlock it (zingaconnect_starter). Build your UI against the counts, and treat
the roster as an enrichment.

QR codes

GET /links/{id}/qr?fmt=png&size=512

Returns the image bytes for the link's short URL — not JSON.

Parameter Default Notes
fmt png png or svg; use svg for print
size 512 PNG pixel size, 64–2000
dark #000000 Foreground colour
light #ffffff Background colour (PNG)
curl "https://api-v1.zingasuite.com/papi/v1/links/<id>/qr?fmt=svg&dark=%23102A43" \
  -H "Authorization: Bearer zk_live_xxx" -o spring-sale.svg

Remember to URL-encode the # in a colour as %23.

The QR encodes the short URL, so it stays valid when you re-point the link. Mint
the link, render the QR once, and print it — the destination stays yours to
change.

Was this helpful?