Jason Stedwell 48d3445b09 docs: document new features, ops env vars, and API surface; refresh roadmap
- README: feature map updated (redirect types, protected links, QR vector
  export, audience analytics, API keys, admin observability, operations);
  API reference covers new endpoints and params. Roadmap now lists
  self-serve accounts, security hardening (rate limiting/CSRF/SSRF guard),
  Stripe billing, custom domains, and remaining power features.
- INSTALL: new environment variables (WEBHOOK_URL, GEOIP_DB_PATH,
  GEO_API_FALLBACK, IP_ANONYMIZE, CLICK_RETENTION_DAYS, BACKUPS,
  BACKUP_DIR, BACKUP_KEEP) with GeoLite2 setup notes and the ip-api.com
  licensing caveat.
- api-docs page: API-key authentication, new link/analytics/QR params,
  aggregate analytics, admin overview/audit/keys/purge, unlock route.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 01:40:44 -05:00
2026-03-06 10:18:49 -06:00
2026-03-06 10:16:10 -06:00
2026-03-06 10:16:10 -06:00
2026-03-06 10:16:10 -06:00
2026-03-06 10:17:59 -06:00
2026-03-06 10:17:59 -06:00
2026-03-06 10:18:15 -06:00
2026-03-06 10:17:59 -06:00
2026-03-06 10:18:15 -06:00
2026-03-06 10:18:15 -06:00
2026-03-06 10:18:15 -06:00

QRknit — URL Shortener & QR Code Generator

A managed URL shortener with QR code generation, deep click analytics, and tag-based link organization.

  • Multi-user — admin account seeded from env vars; admin can create/delete/manage accounts via the UI
  • Per-user isolation — each user sees only their own links and tags; admin has its own isolated workspace separate from all other accounts
  • Organizations — group users into orgs that share link/tag visibility and pool usage quotas under a shared plan
  • Plan tiers — Admin / Free / Starter / Pro / Team with enforced limits on active links, monthly clicks, and analytics history window; org members inherit their org's plan
  • Scoped tags — tags are owned by the user who creates them; org members share a tag namespace, solo users and admins each have their own isolated namespace
  • Deep analytics — daily charts, referrer/device/browser/country breakdowns, hourly 7×24 heatmap, raw click CSV export
  • Private instance — Pro and Team plans include a dedicated private deployment on your own infrastructure

🗺 Feature Map

Shipped

Feature area What's included
Short links Random & custom codes, link expiry, pinned links, one-click copy, auto-fetch page title, per-link redirect type (302 default / 301 opt-in)
Protected links Per-link password protection with a branded unlock page; branded visitor pages for missing, expired, and quota-limited links
QR codes QR generation for any link or URL, logo overlay, dot-shape presets, inline thumbnail, copy to clipboard, SVG / PDF / PNG export, selectable error-correction level (L/M/Q/H)
Analytics Per-link daily click charts, unique-visitor counts, bot/crawler filtering, referrer / device / browser / country breakdowns, hourly 7×24 heatmap, raw click CSV export
Audience analytics Aggregate dashboard across the whole account or org, filterable by tag — one chart for a whole campaign
Tags Tag links for filtering; tags are scoped per user — org members share a namespace, solo users and admins each have their own
Bulk tools Bulk delete, bulk tag, bulk expire; CSV import & export
Auth Session-cookie login, 30-day HttpOnly cookie, API keys (Authorization: Bearer qrk_…) with read/write scopes, works behind Cloudflare and Nginx Proxy Manager
Multi-user Per-user link isolation, admin user-management panel, username + password login
Organizations Group users into orgs that share link/tag visibility and pool usage quotas under a shared plan
Plan tiers Free / Starter / Pro / Team plans with enforced limits on active links, monthly clicks, and analytics history; org plan overrides member plans
Admin tier Admin accounts sit above all plans with unlimited quotas and an isolated workspace; can filter into any user's links on demand
Admin observability Platform overview (totals, 30-day series, top links), per-user/org quota usage with near-limit warnings, audit log of admin actions, webhook notifications for contact messages
Landing & portal Marketing landing page, SaaS pricing page, contact form, admin inbox with unread badge
Operations Async click logging (redirects never block), local GeoLite2 geolocation, daily SQLite backups (VACUUM INTO), click-data retention & IP anonymisation options, hard-purge of deleted links, multi-worker-safe uptime tracking
Deployment APP_NAME / BASE_URL env vars, four colour themes, single Docker container, Unraid-ready

Roadmap

Feature area What's planned
Self-serve accounts Public signup with email verification, change-own-password, account page with plan & usage
Security hardening Rate limiting (login, contact, QR endpoints), CSRF tokens, SSRF guard on title fetching
Billing Stripe checkout & subscriptions, upgrade/downgrade UI, self-serve account portal
Custom domains CNAME-based short domains, SSL provisioning, domain verification, Team tier multi-domain support
Power features UTM parameter builder, dead-link detection, folders/groups, duplicate link

Installing? See INSTALL.md for Docker, Docker Compose, and Unraid setup instructions, environment variables, and update steps.


🔌 API Reference

Authenticated endpoints accept either an active session (log in via the web UI or POST /api/auth/login) or an API key: Authorization: Bearer qrk_…. Keys are created in the dashboard (or via POST /api/keys) with a read or write scope — read-only keys can only call GET endpoints.

Auth & API keys

Method Endpoint Auth Description
POST /api/auth/login Login — {"username": "...", "password": "..."}, sets session cookie; returns plan, plan_limits, org_id
POST /api/auth/logout Clear session
GET /api/auth/me Returns {"authenticated": true, "username": "...", "is_admin": bool, "org_id": int|null, "plan": "...", "plan_limits": {…}}
GET /api/keys List your API keys (prefix, scope, last used — never the full token)
POST /api/keys Create key — {name, scope: "read"|"write"}; response includes token once
DELETE /api/keys/:id Revoke a key (admins can revoke any key)
Method Endpoint Auth Description
POST /api/shorten Create a short link — {url, custom_code?, title?, expires_at?, tags?, redirect_type?: 301|302, password?}
GET /api/links List links — supports ?q=, ?tag=, ?page=, ?per_page=; org members see all links within their org; admin sees own links only, optionally filtered with ?user=<username>
GET /api/links/:code Link detail — includes created_by, redirect_type, has_password
PATCH /api/links/:code Edit link — url, title, expires_at, tags, is_pinned, redirect_type (301/302), password (empty string removes protection)
DELETE /api/links/:code Delete link (soft — recoverable until purged by an admin)
GET /api/links/:code/analytics Click analytics — supports ?days=7|30|90 (capped to plan's max window) and ?exclude_bots=1; returns daily (with per-day unique), unique_visitors, bot_clicks, referrers, devices, browsers, countries, heatmap (7×24 array), and max_days
GET /api/analytics/aggregate Account/org-wide analytics — ?days=, ?tag=, ?exclude_bots=1; returns daily, unique_visitors, referrers, devices, browsers, countries, top_links
GET /api/links/:code/clicks/export Download raw click events as CSV — columns: timestamp, referrer, device, browser, country

Utilities

Method Endpoint Auth Description
GET /api/stats Total links, total clicks, clicks/7d, top 5 links, and a 30-day daily click array for the dashboard chart
GET /api/plan Current user's effective plan, limits, and live usage — {plan, limits: {max_links, monthly_clicks, analytics_days}, usage: {active_links, monthly_clicks}}; org members see pooled usage across all org members; admin plan is always "admin" (unlimited)
GET /api/tags Tags scoped to the requesting user — own tags only for solo users and admins; all org member tags for org members
GET /api/fetch-title Server-side page title fetch — ?url=. Returns {"title":"…"}
GET /api/qr/:code QR for a short link — ?format=png|svg|pdf, ?ec=L|M|Q|H, ?fg=, ?bg=, ?size=, ?style= (raster only), ?download=1
GET /api/qr/custom QR for any URL — same params as above plus ?url=
POST /api/qr/custom QR with logo overlay — {url, fg, bg, size, style, ec, format, logo} (logo as base64; forces error correction H)
POST /api/links/bulk Bulk operations — {action: "delete"|"tag"|"expire", codes: […]}
GET /api/links/export Download all links as CSV
POST /api/links/import Import links from CSV — {csv: "…"}
GET /api/health Health check — {"status":"ok"}
GET /:code Redirect to destination URL (302 by default; 301 if configured per link; password-protected links show a branded unlock page)
POST /:code/unlock Password submission for protected links (form field password)

Admin

Method Endpoint Auth Description
GET /api/admin/users Admin List all users with link counts, plan, org name, and org plan
POST /api/admin/users Admin Create user — {username, password, is_admin, plan}
PATCH /api/admin/users/:id Admin Update plan, admin status, and/or org — {plan?, is_admin?, org_id?} (set org_id: null to remove from org)
DELETE /api/admin/users/:id Admin Delete user (cannot delete self)
PATCH /api/admin/users/:id/password Admin Change user password — {password}
GET /api/admin/organizations Admin List all organizations with member counts and plan
POST /api/admin/organizations Admin Create organization — {name, plan}
PATCH /api/admin/organizations/:id Admin Update organization name and/or plan — {name?, plan?}
DELETE /api/admin/organizations/:id Admin Delete organization — members are unassigned but not deleted
GET /api/admin/messages Admin List all contact/portal messages, newest first
DELETE /api/admin/messages/:id Admin Delete a message
PATCH /api/admin/messages/:id/read Admin Mark a message as read
GET /api/admin/overview Admin Platform totals, 30-day click series, top links, per-user quota usage with near-limit flags
GET /api/admin/audit Admin Audit log of admin actions — ?limit= (default 200)
GET /api/admin/keys Admin List all API keys across users (prefix, scope, last used)
POST /api/admin/purge Admin Hard-delete soft-deleted links older than {days} — frees short codes, removes click history

Contact

Method Endpoint Auth Description
POST /api/contact Submit a contact message — {name, email, subject, body}

Third-party attributions

QRknit is built on open-source components. See NOTICES.md for full licence texts.

Library Licence Used for
Flask BSD-3-Clause Web framework & routing
Werkzeug BSD-3-Clause Password hashing, WSGI utilities
qrcode MIT QR code generation
Pillow HPND Image processing & QR rendering
Gunicorn MIT Production WSGI server
Google Fonts — Orbitron, Barlow, Share Tech Mono OFL-1.1 UI typography

© 2025 QRknit. All rights reserved.

S
Description
QRKnit: commercial QR code generator and URL shortener — create, manage, and track branded QR codes and short links
Readme 1.5 MiB
Languages
HTML 73.1%
Python 26.3%
Dockerfile 0.6%