main
Build and Push Docker Image / build (push) Successful in 1m20s
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) |
Links
| 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.
Description
QRKnit: commercial QR code generator and URL shortener — create, manage, and track branded QR codes and short links
Languages
HTML
73.1%
Python
26.3%
Dockerfile
0.6%