Help Center
Everything you need to get the most out of ScanStack.
Getting started
1. Create your account
Visit /signup and enter your email and password. Choose a plan starting at $19/mo. All plans include a 30-day money-back guarantee.
2. Get your API key
An API key is automatically generated when you sign up. You can find it on your Account Settings page. You can create up to 5 active API keys. API keys start with qr_.
3. Create your first QR code
You can create QR codes two ways:
- •Dashboard — Go to Dashboard → "Create QR Code". Fill in a label, type, and target URL.
- •API — Send a POST request to
https://api.scanstack.dev/qr/dynamicwith your API key.
4. Share & track
Download the QR code image or use the short link (e.g. https://scanstack.dev/r/abc123). Every scan is tracked with analytics available in your dashboard and via the API.
Using the dashboard
QR code list
Your Dashboard shows all your dynamic QR codes. Each entry displays the label, short code, target URL, total scans, and status (active/inactive). Click any QR code to view full details.
Creating a QR code
Click "Create QR Code" from the dashboard. You'll need:
- •Label — A friendly name (e.g., "Spring Sale Flyer")
- •Type — URL or Text
- •Target URL — Where scans will redirect to
QR code details
The detail page for each QR code shows:
- •Short code & redirect URL — The scannable link
- •Target URL editor — Update the destination without changing the QR code
- •Analytics — Total scans, scans in the last 30 days, and a daily scan chart
- •QR preview & download — Download the QR code as a PNG image
- •Deactivate — Permanently stop the short link from redirecting
Dynamic QR codes
Dynamic QR codes point to a short redirect link (e.g., scanstack.dev/r/abc123) instead of directly to your target URL. This means:
- ✓Change the destination anytime — Update where the QR code points without reprinting
- ✓Track every scan — See scan counts, dates, user agents, and more
- ✓Add smart routing — Use conditional redirects to send users to different URLs based on device, OS, or location
- ✓Run A/B tests — Split traffic between multiple landing pages
Static vs. Dynamic: Static QR codes encode the URL directly into the QR pattern. They can't be tracked or updated. Use the /qr/static endpoint for static codes. Dynamic codes use /qr/dynamic.
Conditional redirects
Starter plan and aboveRoute scans to different URLs based on the scanner's device, operating system, country, or language. Rules are evaluated by priority (highest first). If no rule matches, the default target URL is used.
Condition types
| Type | Values | Example use case |
|---|---|---|
| device | mobile, tablet, desktop | Send mobile users to a mobile-optimized page |
| os | ios, android, windows, macos, linux | Redirect iOS to the App Store, Android to Google Play |
| country | ISO country codes (US, GB, DE, etc.) | Show region-specific landing pages |
| language | ISO language codes (en, es, fr, etc.) | Serve content in the user's language |
| default | — | Fallback if no other rule matches |
How to set up (API)
POST https://api.scanstack.dev/v2/qr/:id/rules
{
"condition_type": "os",
"condition_value": "ios",
"target_url": "https://apps.apple.com/your-app",
"priority": 10
}
Rules with higher priority numbers are evaluated first. You can add multiple rules to a single QR code.
A/B testing
Pro plan and aboveSplit traffic from a single QR code between multiple URL variants. Each variant has a configurable weight that controls what percentage of scans go to each URL. ScanStack tracks scan counts per variant so you can measure performance.
How to set up
POST https://api.scanstack.dev/v2/qr/:id/ab-test
{
"variants": [
{ "label": "Landing Page A", "target_url": "https://example.com/a", "weight": 50 },
{ "label": "Landing Page B", "target_url": "https://example.com/b", "weight": 50 }
]
}
Reading results
Use GET /v2/qr/:id/ab-test to see scan counts and conversion rates per variant. When you've found a winner, delete the A/B test and update the QR code's target URL to the winning variant.
Tip: Start with a 50/50 split and run the test for at least 100 total scans before drawing conclusions. You can adjust weights over time to send more traffic to the winning variant.
Campaigns
Starter plan and aboveCampaigns let you organize QR codes into named groups for project-level management. For example, you might create a campaign called "Q1 Product Launch" and assign all related QR codes to it.
Managing campaigns (API)
- •Create:
POST /v2/campaignswith{ "name": "...", "description": "..." } - •List:
GET /v2/campaigns— returns all campaigns with QR code counts - •Assign a QR code:
POST /v2/qr/:id/campaignwith{ "campaign_id": "..." } - •Delete:
DELETE /v2/campaigns/:id— QR codes are unassigned but not deleted
You can also assign a campaign during bulk generation by including campaign_id in each item.
Bulk generation
Starter plan and aboveCreate up to 100 dynamic QR codes in a single API request. This is useful for generating QR codes for product catalogs, event tickets, inventory labels, or any scenario requiring many codes at once.
POST https://api.scanstack.dev/v2/bulk
{
"items": [
{ "type": "url", "data": { "url": "https://page-1.com" }, "label": "Product 1" },
{ "type": "url", "data": { "url": "https://page-2.com" }, "label": "Product 2" },
{ "type": "url", "data": { "url": "https://page-3.com" }, "label": "Product 3", "campaign_id": "camp_xxx" }
]
}
The response includes an array of created QR codes, each with its id, short_code, redirect_url, and qr_image (base64).
Scan webhooks
Pro plan and aboveReceive real-time HTTP POST notifications when events occur. Webhooks are signed with HMAC-SHA256 for security.
Available events
| Event | Description |
|---|---|
| scan.completed | Fired when any of your QR codes is scanned |
| qr.created | A new QR code was created |
| qr.updated | A QR code's target URL was changed |
| qr.deactivated | A QR code was deactivated |
| * | Subscribe to all events |
Setting up a webhook
POST https://api.scanstack.dev/v2/webhooks
{
"url": "https://your-server.com/webhook",
"events": ["scan.completed"]
}
The response includes a signing secret. Verify incoming webhooks by checking the x-webhook-signature header against an HMAC-SHA256 of the request body.
Auto-disable: Webhooks automatically deactivate after 10 consecutive delivery failures to prevent cascading errors.
API quickstart
Authentication
All API requests require your API key. Pass it as a header or query parameter:
# Header (recommended)
curl -H "x-api-key: qr_your_key_here" https://api.scanstack.dev/qr/dynamic
# Query parameter
curl "https://api.scanstack.dev/qr/dynamic?api_key=qr_your_key_here"
Create a dynamic QR code
curl -X POST https://api.scanstack.dev/qr/dynamic \
-H "x-api-key: qr_your_key_here" \
-H "Content-Type: application/json" \
-d '{"type":"url","data":{"url":"https://example.com"},"label":"My QR Code"}'
Update the target URL
curl -X PATCH https://api.scanstack.dev/qr/dynamic/YOUR_QR_ID \
-H "x-api-key: qr_your_key_here" \
-H "Content-Type: application/json" \
-d '{"target_url":"https://new-destination.com"}'
Get scan analytics
curl https://api.scanstack.dev/analytics/YOUR_QR_ID/stats?days=30 \
-H "x-api-key: qr_your_key_here"
For the full API reference including all endpoints, request/response formats, and supported QR types (URL, WiFi, vCard, email, SMS, text), see the API Documentation.
QR code styling
Customize QR codes with colors, logos, and rounded corners via the style object in API requests.
| Option | Type | Default | Description |
|---|---|---|---|
| width | number | 512 | Image width in pixels (64–2048) |
| margin | number | 2 | Quiet zone around the code (0–10) |
| foregroundColor | string | #000000 | Hex color for modules (dark squares) |
| backgroundColor | string | #FFFFFF | Hex color for background |
| errorCorrectionLevel | string | H | L (7%), M (15%), Q (25%), H (30%) |
| logoUrl | string | — | URL to a logo image to embed in the center |
| logoBase64 | string | — | Base64-encoded logo (alternative to URL) |
| logoScale | number | 0.2 | Logo size as a ratio of the QR code (0.1–0.35) |
| cornerRadius | number | 0 | Rounded corners in pixels |
Tip: When adding a logo, use error correction level H (default) to maintain scannability. Keep the logo scale at 0.2 or below for best results.
Supported QR types
| Type | Data fields | Use case |
|---|---|---|
| url | url | Link to any website or web app |
| wifi | ssid, password, encryption, hidden | Auto-connect to WiFi networks |
| vcard | name, organization, phone, email, url, address | Share contact info |
to, subject, body | Pre-fill an email draft | |
| sms | phone, message | Pre-fill an SMS message |
| text | text | Encode any plain text |
Account & billing
API keys
Manage API keys from Account Settings. You can have up to 5 active keys. Keys can be labeled for easy identification (e.g., "Production", "Staging"). Revoking a key is permanent and immediate.
Changing your password
Go to Account Settings and use the password change form. Passwords must be at least 8 characters.
Upgrading your plan
Visit Pricing and click "Upgrade" on any paid plan. You'll be redirected to a secure Stripe checkout. Your plan activates instantly after payment. Both monthly and yearly billing are available (save 20% with yearly).
Managing your subscription
Access the Stripe billing portal from Account Settings to update your payment method, view invoices, or cancel your subscription. If you cancel within 30 days, you're eligible for a full refund.
Plans & limits
| Feature | Starter ($19/mo) | Pro ($49/mo) | Business ($149/mo) |
|---|---|---|---|
| Dynamic QR codes | 50 | 500 | Unlimited |
| API requests/day | 5,000 | 50,000 | Unlimited |
| Scans/month | Unlimited | ||
| Analytics | Full | ||
| Output formats | PNG, SVG, Base64 | ||
| Conditional redirects | ✓ | ✓ | ✓ |
| Campaigns | ✓ | ✓ | ✓ |
| Custom branding | ✓ | ✓ | ✓ |
| Bulk generation | 100/batch | 100/batch | 100/batch |
| A/B testing | ✗ | ✓ | ✓ |
| Scan webhooks | ✗ | ✓ | ✓ |
| White-label | ✗ | ✗ | ✓ |
| Team seats | 1 | 1 | 10 |
| SLA guarantee | ✗ | ✗ | ✓ |
Save 20% with yearly billing. View pricing details →
Partner program
Earn recurring revenue by referring clients to ScanStack. Partners earn 20–30% lifetime commission on every subscription payment from their referred users.
- ✓20% commission — for referral-only partners
- ✓30% commission — for partners who fully onboard and support their referrals
- ✓90-day cookie — if someone clicks your link and signs up within 90 days, you get credit
- ✓Monthly payouts — via PayPal once your balance reaches $50
- ✓Real-time dashboard — track referrals, conversions, and earnings
Ideal for marketing consultants, e-commerce coaches, developer content creators, and print/signage companies.
Frequently asked questions
What happens if I exceed my plan limits?
API requests beyond your daily limit will return a 429 Too Many Requests error. You won't be charged overage fees. Upgrade your plan anytime to increase limits.
Can I change where a QR code points after printing?
Yes — that's the core benefit of dynamic QR codes. Update the target URL from the dashboard or via the API at any time without changing the printed QR code.
What QR code formats are supported?
PNG and Base64 are available on all plans. SVG is available on Starter and above. Static QR codes default to PNG; dynamic codes return Base64 by default.
Do QR codes expire?
No. Dynamic QR codes remain active as long as your account is active. If you deactivate a QR code, the short link will stop redirecting, but the code itself is preserved in your account.
What happens if I downgrade or cancel?
Your existing QR codes remain active. However, if your QR code count exceeds the new plan's limit, you won't be able to create new ones until you're within the limit. Features exclusive to higher plans (A/B testing, webhooks, etc.) will no longer be accessible via the API.
Is there an uptime guarantee?
Business plan customers receive an SLA guarantee. All plans benefit from the same infrastructure, but the SLA provides contractual uptime commitments and priority support.
How do I verify webhook signatures?
When you create a webhook, ScanStack returns a signing secret. For each delivery, compute an HMAC-SHA256 of the raw request body using that secret and compare it to the x-webhook-signature header value.
Can I use ScanStack for offline/print campaigns?
Absolutely. That's one of the most common use cases. Create dynamic QR codes, print them on packaging, flyers, posters, or business cards, and update the destination URL anytime without reprinting.
Can I add my logo to QR codes?
Yes. Use the logoUrl or logoBase64 style option. The logo is embedded in the center of the QR code. Use error correction level H (default) for best scannability with logos.
I need help. How do I contact support?
Email us at support@scanstack.dev. We typically respond within 24 hours on business days.