Overview
The QR Code Public API allows developers to programmatically create, manage, and track QR codes from their applications.
Base URL
http://qr.scanalyzr.com/api/v1/publicKey Features
Simplified Creation
Just provide a name and destination URL
Dynamic QR Codes
Update destinations without regenerating
IP-Based Tracking
Automatic scan tracking and analytics
Custom Short Codes
Use your own branded short codes
Authentication
The API supports three authentication methods. We recommend using the X-API-Key header.
RecommendedMethod 1: X-API-Key Header
fetch('http://qr.scanalyzr.com/api/v1/public/qr', {
headers: {
'X-API-Key': 'qr_live_your_api_key_here',
'Content-Type': 'application/json'
}
});Method 2: Authorization Bearer Token
fetch('http://qr.scanalyzr.com/api/v1/public/qr', {
headers: {
'Authorization': 'Bearer qr_live_your_api_key_here',
'Content-Type': 'application/json'
}
});Not RecommendedMethod 3: Query Parameter
http://qr.scanalyzr.com/api/v1/public/qr?apiKey=qr_live_your_api_key_here
⚠️ Avoid in production - API keys may appear in server logs
Quick Start
Step 1: Get Your API Key
- Log in to your QR Code dashboard
- Navigate to Settings → API Keys
- Click "Create API Key"
- Copy your API key (starts with
qr_live_)
Step 2: Make Your First Request
curl -X POST http://qr.scanalyzr.com/api/v1/public/qr \
-H "X-API-Key: qr_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My First QR Code",
"destinationUrl": "https://example.com",
"shortCode": "my-first-qr"
}'Step 3: Response
{
"success": true,
"message": "QR code created successfully",
"data": {
"id": "cm5abc123xyz",
"name": "My First QR Code",
"shortCode": "my-first-qr",
"shortUrl": "https://your-domain.com/q/my-first-qr",
"qrCodeUrl": "https://res.cloudinary.com/.../my-first-qr.png",
"destinationUrl": "https://example.com",
"type": "URL",
"scanCount": 0,
"isActive": true,
"createdAt": "2026-01-18T10:30:00.000Z"
}
}Create QR Code
/api/v1/public/qrCreates a new dynamic QR code with default settings.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | ✅ Yes | Descriptive name for your QR code |
| destinationUrl | string | ✅ Yes | Where the QR code should redirect |
| shortCode | string | ❌ No | Custom short code (auto-generated if omitted) |
| type | string | ❌ No | QR data type (default: "URL") |
Example Request
const createQRCode = async () => {
const response = await fetch('http://qr.scanalyzr.com/api/v1/public/qr', {
method: 'POST',
headers: {
'X-API-Key': 'qr_live_your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Product Launch Campaign',
destinationUrl: 'https://example.com/product/launch',
shortCode: 'launch24'
})
});
const data = await response.json();
console.log('QR Code Created:', data.data.qrCodeUrl);
return data;
};List QR Codes
/api/v1/public/qrRetrieves all QR codes associated with your API key, with pagination support.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number |
| limit | number | 10 | Items per page (max 100) |
const getQRCodes = async (page = 1, limit = 10) => {
const response = await fetch(
`http://qr.scanalyzr.com/api/v1/public/qr?page=${page}&limit=${limit}`,
{
headers: {
'X-API-Key': 'qr_live_your_api_key_here'
}
}
);
return await response.json();
};Get Single QR Code
/api/v1/public/qr/:idRetrieves detailed information about a specific QR code.
URL Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string | QR code ID |
Example Request
const getQRCode = async (qrCodeId) => {
const response = await fetch(
`http://qr.scanalyzr.com/api/v1/public/qr/${qrCodeId}`,
{
headers: {
'X-API-Key': 'qr_live_your_api_key_here'
}
}
);
return await response.json();
};Example Response (200 OK)
{
"success": true,
"message": "QR code retrieved successfully",
"data": {
"id": "cm5abc123xyz",
"name": "Product Launch Campaign",
"shortCode": "launch24",
"shortUrl": "https://your-domain.com/q/launch24",
"qrCodeUrl": "https://res.cloudinary.com/.../launch24.png",
"destinationUrl": "https://example.com/product/launch",
"type": "URL",
"scanCount": 42,
"isActive": true,
"createdAt": "2026-01-17T10:30:00.000Z"
}
}Update QR Code
/api/v1/public/qr/:idUpdates an existing QR code's name, destination URL, or active status.
📝 Note: For dynamic QR codes, updating the destination URL will regenerate the QR image.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | ❌ No | New name for the QR code |
| destinationUrl | string | ❌ No | New destination URL |
| isActive | boolean | ❌ No | Enable/disable the QR code |
Example Request
const updateQRCode = async (qrCodeId, updates) => {
const response = await fetch(
`http://qr.scanalyzr.com/api/v1/public/qr/${qrCodeId}`,
{
method: 'PATCH',
headers: {
'X-API-Key': 'qr_live_your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
return await response.json();
};
// Usage
await updateQRCode('cm5abc123xyz', {
destinationUrl: 'https://example.com/new-destination',
isActive: true
});Example Response (200 OK)
{
"success": true,
"message": "QR code updated successfully",
"data": {
"id": "cm5abc123xyz",
"name": "Updated Campaign Name",
"shortCode": "launch24",
"shortUrl": "https://your-domain.com/q/launch24",
"qrCodeUrl": "https://res.cloudinary.com/.../launch24.png",
"destinationUrl": "https://example.com/new-destination",
"type": "URL",
"scanCount": 42,
"isActive": true,
"createdAt": "2026-01-17T10:30:00.000Z"
}
}Delete QR Code
/api/v1/public/qr/:idPermanently deletes a QR code and all its associated scan data.
⚠️ Warning: This action cannot be undone! The QR code and all its analytics will be permanently deleted.
URL Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string | QR code ID to delete |
Example Request
const deleteQRCode = async (qrCodeId) => {
const response = await fetch(
`http://qr.scanalyzr.com/api/v1/public/qr/${qrCodeId}`,
{
method: 'DELETE',
headers: {
'X-API-Key': 'qr_live_your_api_key_here'
}
}
);
return await response.json();
};Example Response (200 OK)
{
"success": true,
"message": "QR code deleted successfully",
"data": {
"message": "QR code deleted successfully"
}
}Get QR Code Analytics
/api/v1/public/qr/:id/analyticsRetrieves comprehensive analytics for a specific QR code including total scans, unique scans, and scan breakdowns by date, location, and device.
Example Request
const getAnalytics = async (qrCodeId) => {
const response = await fetch(
`http://qr.scanalyzr.com/api/v1/public/qr/${qrCodeId}/analytics`,
{
headers: {
'X-API-Key': 'qr_live_your_api_key_here'
}
}
);
const data = await response.json();
console.log('Total Scans:', data.data.analytics.totalScans);
console.log('Unique Users:', data.data.analytics.uniqueScans);
return data;
};Example Response (200 OK)
{
"success": true,
"message": "QR code analytics retrieved successfully",
"data": {
"qrCode": {
"id": "cm5abc123xyz",
"name": "Product Launch Campaign",
"shortUrl": "https://your-domain.com/q/launch24",
"destinationUrl": "https://example.com/product/launch"
},
"analytics": {
"totalScans": 156,
"uniqueScans": 89,
"recentScans": 23,
"scansByDate": {
"2026-01-15": 45,
"2026-01-16": 67,
"2026-01-17": 44
},
"scansByLocation": {
"United States": 89,
"Canada": 34,
"United Kingdom": 23,
"Germany": 10
},
"scansByDevice": {
"mobile": 112,
"desktop": 34,
"tablet": 10
}
}
}
}🔒 Advanced Features
Enhance your QR codes with password protection, expiration dates, scan limits, and custom designs.
🔐 Password Protection
Restrict access to your QR code content with password protection. Users must enter the correct password before accessing the destination URL.
{
"name": "Private Document",
"destinationUrl": "https://example.com/private/document.pdf",
"password": "secure123" // 4-50 characters
}- Minimum length: 4 characters
- Maximum length: 50 characters
- Case-sensitive
⏰ Expiration Date
Set an automatic expiration date for time-sensitive campaigns. QR code becomes inactive after the specified date.
{
"name": "Flash Sale",
"destinationUrl": "https://example.com/flash-sale",
"expiresAt": "2026-12-31T23:59:59Z" // ISO 8601 format
}Behavior: After expiration, scans redirect to an "expired" message page
📊 Scan Limit
Control the maximum number of scans allowed. Perfect for limited offers, single-use tickets, or beta access codes.
{
"name": "Limited Offer",
"destinationUrl": "https://example.com/offer",
"scanLimit": 100 // Maximum number of scans
}Note: Limit can be increased by updating the QR code
🎨 Custom Design
Fully customize the appearance of your QR codes - colors, size, dots style, corners, gradients, and logos.
{
"name": "Branded QR",
"destinationUrl": "https://example.com",
"customDesign": {
// Basic Options
"backgroundColor": "#FFFFFF",
"foregroundColor": "#000000",
"margin": 4,
"width": 500,
"errorCorrectionLevel": "M", // L, M, Q, H
// Advanced Styling
"dotsType": "rounded", // rounded, dots, classy, square
"dotsColor": "#FF6B35",
"cornersSquareType": "extra-rounded",
"cornersSquareColor": "#FF6B35",
// Logo (optional)
"imageUrl": "https://example.com/logo.png",
"imageMargin": 10,
"imageSize": 0.3
}
}Color Options: Use hex format (e.g., #FF6B35)
Size Range: 100-2000 pixels
Error Correction: L (7%), M (15%), Q (25%), H (30%)
Logo Size: 0.1-0.5 (relative to QR code size)
🎯 Combined Features Example
Use multiple advanced features together for maximum security and customization:
{
"name": "VIP Event Ticket",
"destinationUrl": "https://example.com/event/checkin",
// Security Features
"password": "vip2024",
"expiresAt": "2026-06-15T23:59:59Z",
"scanLimit": 1, // Single-use ticket
// Custom Branding
"customDesign": {
"backgroundColor": "#1E3A8A",
"foregroundColor": "#FBBF24",
"margin": 6,
"width": 800,
"dotsType": "rounded",
"errorCorrectionLevel": "H",
"imageUrl": "https://example.com/event-logo.png",
"imageSize": 0.25
}
}💡 Common Use Cases
Single-Use Tickets
scanLimit: 1, expiresAt: event-dateBeta Access Codes
password + expiresAtTime-Limited Promos
expiresAt onlyBranded Marketing
customDesign with logoQR Code Types (19 Available)
The API supports 19 different QR code types. All types are fully functional in the application. Below are the data structures required for each type.
📋 Quick Navigation - Jump to Type:
1. URL - Website Links
API ReadyRedirects users to a website or web page.
{
"name": "Company Website",
"type": "URL",
"destinationUrl": "https://example.com"
}2. WIFI - Network Credentials
AvailableShares WiFi network credentials. Automatically connects when scanned.
{
"name": "Office WiFi",
"type": "WIFI",
"qrData": {
"ssid": "MyNetwork",
"password": "SecurePassword123",
"encryption": "WPA", // Options: "WPA", "WEP", "nopass"
"hidden": false // true for hidden networks
}
}3. EMAIL - Pre-filled Email
AvailableComposes a pre-filled email when scanned.
{
"name": "Support Email",
"type": "EMAIL",
"qrData": {
"email": "support@example.com",
"subject": "Customer Inquiry",
"body": "Hello, I would like to know more about..."
}
}4. PHONE - Phone Call
AvailableInitiates a phone call when scanned.
{
"name": "Customer Service",
"type": "PHONE",
"qrData": {
"phone": "+1-800-123-4567"
}
}5. SMS - Text Message
AvailableSends a pre-filled SMS message when scanned.
{
"name": "Text to Win",
"type": "SMS",
"qrData": {
"phone": "+1234567890",
"message": "JOIN to enter the contest"
}
}6. WHATSAPP - WhatsApp Message
AvailableOpens WhatsApp chat with pre-filled message.
{
"name": "WhatsApp Support",
"type": "WHATSAPP",
"qrData": {
"phone": "+1234567890", // Include country code
"message": "Hi! I'm interested in your services"
}
}7. LOCATION - GPS Coordinates
AvailableOpens map application with specific coordinates.
{
"name": "Office Location",
"type": "LOCATION",
"qrData": {
"latitude": 40.7128,
"longitude": -74.0060,
"address": "123 Main Street, New York, NY" // Optional
}
}8. CONTACT - vCard
AvailableShares complete contact information (vCard format).
{
"name": "John Doe Contact",
"type": "CONTACT",
"qrData": {
"firstName": "John",
"lastName": "Doe",
"organization": "Acme Corp",
"title": "CEO",
"phone": "+1234567890",
"email": "john@example.com",
"website": "https://johndoe.com",
"address": {
"street": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "USA"
}
}
}9. EVENT - Calendar Event
AvailableAdds an event to the user's calendar.
{
"name": "Conference Event",
"type": "EVENT",
"qrData": {
"title": "Tech Conference 2026",
"description": "Annual technology conference",
"location": "Convention Center, NYC",
"startDate": "2026-06-15T09:00:00Z",
"endDate": "2026-06-15T17:00:00Z",
"allDay": false
}
}10. MECARD - Lightweight Contact
AvailableLightweight contact card format (alternative to vCard).
{
"name": "Business Card",
"type": "MECARD",
"qrData": {
"name": "John Doe",
"phone": "+1234567890",
"email": "john@example.com",
"url": "https://johndoe.com",
"address": "123 Main St, NYC"
}
}11. PDF - Document Link
AvailableDirect link to a PDF document.
{
"name": "Product Brochure",
"type": "PDF",
"destinationUrl": "https://example.com/brochure.pdf"
}12. VIDEO - Video Link
AvailableDirect link to a video.
{
"name": "Product Demo",
"type": "VIDEO",
"destinationUrl": "https://youtube.com/watch?v=xxx"
}13. AUDIO - Audio Link
AvailableDirect link to an audio file or podcast.
{
"name": "Podcast Episode",
"type": "AUDIO",
"destinationUrl": "https://example.com/podcast.mp3"
}15. GOOGLE_REVIEW - Review Link
AvailableDirect link to Google Business review page.
{
"name": "Leave a Review",
"type": "GOOGLE_REVIEW",
"destinationUrl": "https://g.page/r/YOUR_PLACE_ID/review"
}16. COUPON - Discount Code
AvailableDisplays a coupon or discount code.
{
"name": "10% Off Coupon",
"type": "COUPON",
"destinationUrl": "https://example.com/redeem?code=SAVE10"
}17. FEEDBACK - Feedback Form
AvailableDirect link to feedback form.
{
"name": "Customer Feedback",
"type": "FEEDBACK",
"destinationUrl": "https://forms.google.com/yourform"
}18. BUSINESS_PAGE - Business Profile
AvailableComprehensive business information page.
{
"name": "Business Profile",
"type": "BUSINESS_PAGE",
"destinationUrl": "https://yourbusiness.com/profile"
}19. TEXT - Plain Text
AvailableDisplays plain text when scanned.
{
"name": "WiFi Password",
"type": "TEXT",
"destinationUrl": "Password: SecurePass123"
}💡 Using Advanced QR Types
All 19 QR types are fully functional in the application dashboard. Simply select the desired type in the "Create QR Code" tab and fill in the required fields. The system will automatically generate the appropriate QR code with the correct data format.
Error Handling
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | QR code created successfully |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | QR code limit reached |
| 404 | Not Found | QR code not found |
| 409 | Conflict | Short code already exists |
| 429 | Too Many Requests | Rate limit exceeded |
Error Response Format
{
"success": false,
"message": "QR code limit reached (10). Please upgrade your plan.",
"errorMessages": [
{
"path": "",
"message": "QR code limit reached (10). Please upgrade your plan."
}
]
}Rate Limits & Quotas
| Plan | QR Codes | API Requests/Hour | Scans/QR |
|---|---|---|---|
| Free | 10 | 100 | 100 |
| Basic | 50 | 500 | 1,000 |
| Pro | 200 | 2,000 | Unlimited |
| Business | Unlimited | 10,000 | Unlimited |
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1705492800
Best Practices
✅ Use Environment Variables
// ❌ Bad const apiKey = 'qr_live_abc123...'; // ✅ Good const apiKey = process.env.QR_API_KEY;
✅ Implement Proper Error Handling
async function createQRSafely(data) {
try {
const result = await client.createQR(data);
return { success: true, data: result };
} catch (error) {
console.error('Failed to create QR:', error.message);
return { success: false, error: error.message };
}
}✅ Use Custom Short Codes for Branding
// ✅ Branded short code
await client.createQR({
name: 'Product Page',
destinationUrl: 'https://example.com/product',
shortCode: 'product-2024'
});
// Result: https://your-domain.com/q/product-2024✅ Implement Caching
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function getQRCodeCached(id) {
const cached = cache.get(id);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const data = await client.getQRCode(id);
cache.set(id, { data, timestamp: Date.now() });
return data;
}