QR Tiger API Integration (Option 1)
This document describes Option 1: QR Tiger API (cloud service with ongoing costs). Before implementing Epic 2, evaluate whether this is the best option.
Alternative: QRCoder (free open-source .NET library with zero costs and no rate limits)
See QR Generation Research & Decision for evaluation questions and comparison.
QR code generation system using QR Tiger cloud API for creating scannable QR codes that link to audio playback pages.
QR TIGER API ENDPOINT
QR code generation is implemented in Epic 2 and builds upon the audio generation system from Epic 1.
Note: This document assumes QR Tiger API is chosen. If QRCoder is selected instead, implementation will be simpler, faster, and cost-free.
Overview
Epic 2 adds QR code generation to the existing text-to-speech submission flow. When audio is generated (Epic 1), a QR code is automatically created that links to the audio playback page.
What Changed from Epic 1
Epic 1 (Audio Only):
User Input → ElevenLabs → Audio File → S3 → Playback Link
Epic 2 (Audio + QR Code):
User Input → ElevenLabs → Audio File → S3 → Playback Link → QR Tiger → QR Code → S3
New Capabilities:
- QR code generation for each audio submission
- QR code images stored in S3
- QR code URLs returned in API responses
- Downloadable QR codes for physical distribution
QR Tiger API Configuration
API Details
- Base URL:
https://api.qrtiger.com - Endpoint:
POST /v1/qr - Authentication: Bearer token (API Key)
- Rate Limits: Varies by QR Tiger plan
- Documentation: https://www.qrtiger.com/api-documentation
API Credentials
Configure the following environment variables:
QRTIGER_API_KEY=your_api_key_here
QRTIGER_API_URL=https://api.qrtiger.com/v1/qr
QR Code Generation
Generate QR Code Endpoint
API Call: POST https://api.qrtiger.com/v1/qr
Headers:
Authorization: Bearer {QRTIGER_API_KEY}
Content-Type: application/json
Request Body:
{
"url": "https://micdots.com/play/welcome-audio-qr-service-1706882400123",
"size": 500,
"format": "png",
"errorCorrection": "H"
}
Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The playback URL to encode in the QR code |
size | number | No | QR code dimensions in pixels (default: 500) |
format | string | Yes | Output format: "png" (only PNG supported) |
errorCorrection | string | No | Error correction level: "L", "M", "Q", "H" (default: "H") |
Error Correction Levels:
- L (Low): 7% damage tolerance
- M (Medium): 15% damage tolerance
- Q (Quartile): 25% damage tolerance
- H (High): 30% damage tolerance (recommended for printing)
Response: 200 OK
{
"success": true,
"data": {
"qrCodeUrl": "https://qrtiger.com/qr/abc123def456.png",
"qrCodeId": "abc123def456",
"size": 500,
"format": "png",
"expires": null
}
}
Error Response: 400 Bad Request
{
"success": false,
"error": {
"code": "INVALID_URL",
"message": "The provided URL is invalid or unreachable"
}
}
Error Response: 401 Unauthorized
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid or expired API key"
}
}
Error Response: 429 Too Many Requests
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded. Please try again later."
}
}
Integration with Text-to-Speech API
Updated Processing Flow (Epic 2)
The text-to-speech submission API (POST /api/v1/text-to-speech) is extended in Epic 2 to include QR code generation:
Epic 1 Flow (Audio Only):
- Validate text length and voice ID
- Populate
clientIdandcreatedByfrom JWT token - Generate unique slug
- Generate audio via ElevenLabs
- Upload audio to S3
- Save submission record
- Return audio URL and playback link
Epic 2 Flow (Audio + QR Code) - Added Steps:
- Validate text length and voice ID
- Populate
clientIdandcreatedByfrom JWT token - Generate unique slug
- Generate audio via ElevenLabs
- Upload audio to S3
- 🆕 [NEW] Generate QR code via QR Tiger API (points to playback URL)
- 🆕 [NEW] Upload QR code image to S3
- Save submission record with QR code URL
- Return audio URL, playback link, and QR code URL
Updated Entity Schema (Epic 2)
The TextToSpeechSubmission entity now includes QR code information:
interface TextToSpeechSubmission {
id: string;
text: string;
voiceId: string;
clientId: string;
slug: string;
audioUrl: string;
qrCodeUrl: string; // 🆕 [NEW] Epic 2: S3 URL of QR code image
status: string;
characterCount: number;
processingTime: number;
createdAt: string;
createdBy: {
userId: string;
userName: string;
};
}
Updated API Response (Epic 2)
Response: 201 Created
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Welcome to our audio QR code service.",
"voiceId": "rachel-voice-id-123",
"clientId": "client-abc-123",
"slug": "welcome-audio-qr-service-1706882400123",
"audioUrl": "https://s3.amazonaws.com/micdots-audio/welcome-audio-qr-service-1706882400123.mp3",
"qrCodeUrl": "https://s3.amazonaws.com/micdots-qr/welcome-audio-qr-service-1706882400123.png",
"status": "completed",
"characterCount": 38,
"processingTime": 7850,
"createdAt": "2024-01-22T14:30:00Z",
"createdBy": {
"userId": "user-id-456",
"userName": "John Doe"
}
},
"links": {
"share": "https://micdots.com/play/welcome-audio-qr-service-1706882400123",
"audio": "https://s3.amazonaws.com/micdots-audio/welcome-audio-qr-service-1706882400123.mp3",
"qrCode": "https://s3.amazonaws.com/micdots-qr/welcome-audio-qr-service-1706882400123.png"
}
}
Changes from Epic 1:
- ✅
qrCodeUrlfield added to data object - ✅
qrCodelink added to links object - ✅
processingTimeis slightly longer (includes QR generation time)
AWS S3 Storage for QR Codes
QR code images are stored in a dedicated S3 bucket alongside audio files.
S3 Bucket Configuration
- QR Bucket:
micdots-qr - Region: us-east-1
- Access: Public read
- Format: PNG
- File Naming:
{slug}.png- Example:
welcome-audio-qr-service-1706882400123.png - Same slug as audio file for consistency
- Example:
Upload QR Code to S3
// After generating QR code via QR Tiger
const qrImageResponse = await fetch(qrTigerResponse.data.qrCodeUrl);
const qrImageBuffer = await qrImageResponse.arrayBuffer();
// Upload to S3
const qrKey = `${slug}.png`;
await s3.putObject({
Bucket: "micdots-qr",
Key: qrKey,
Body: qrImageBuffer,
ContentType: "image/png",
ACL: "public-read",
});
const qrCodeUrl = `https://s3.amazonaws.com/micdots-qr/${qrKey}`;
Important: The QR code filename matches the audio slug to maintain consistency across resources.
Implementation Example
Complete Epic 2 Flow
async function generateTextToSpeechWithQR(
text: string,
voiceId: string,
clientId: string
) {
// Step 1: Generate unique slug
const slug = generateSlugFromText(text); // e.g., "welcome-audio-1706882400123"
// Step 2: Generate audio (Epic 1)
const audioBuffer = await elevenLabsAPI.generateSpeech(text, voiceId);
// Step 3: Upload audio to S3
const audioKey = `${slug}.mp3`;
await s3.putObject({
Bucket: "micdots-audio",
Key: audioKey,
Body: audioBuffer,
ContentType: "audio/mpeg",
ACL: "public-read",
});
const audioUrl = `https://s3.amazonaws.com/micdots-audio/${audioKey}`;
const playbackUrl = `https://micdots.com/play/${slug}`;
// Step 4: Generate QR code (Epic 2)
const qrResponse = await fetch("https://api.qrtiger.com/v1/qr", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.QRTIGER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: playbackUrl,
size: 500,
format: "png",
errorCorrection: "H",
}),
});
const qrData = await qrResponse.json();
// Step 5: Download QR code image from QR Tiger
const qrImageResponse = await fetch(qrData.data.qrCodeUrl);
const qrImageBuffer = await qrImageResponse.arrayBuffer();
// Step 6: Upload QR code to S3
const qrKey = `${slug}.png`;
await s3.putObject({
Bucket: "micdots-qr",
Key: qrKey,
Body: qrImageBuffer,
ContentType: "image/png",
ACL: "public-read",
});
const qrCodeUrl = `https://s3.amazonaws.com/micdots-qr/${qrKey}`;
// Step 7: Save to database
const submission = await database.createSubmission({
text,
voiceId,
clientId,
slug,
audioUrl,
qrCodeUrl, // New in Epic 2
status: "completed",
});
return {
success: true,
data: submission,
links: {
share: playbackUrl,
audio: audioUrl,
qrCode: qrCodeUrl,
},
};
}
Integration Flow Diagram
Epic 2 Complete Flow
Key Changes Highlighted:
- Blue section: Epic 1 flow (audio generation)
- Red section: Epic 2 additions (QR code generation)
Error Handling
QR Tiger API Errors
Scenario 1: QR Tiger API is unavailable
try {
const qrResponse = await generateQRCode(playbackUrl);
} catch (error) {
// Log error but don't fail the entire submission
console.error("QR code generation failed:", error);
// Save submission without QR code
await database.createSubmission({
...submissionData,
qrCodeUrl: null, // No QR code available
status: "completed_without_qr",
});
// Return partial success
return {
success: true,
data: submission,
warnings: [
"QR code generation failed. Audio is available but QR code could not be created.",
],
};
}
Scenario 2: QR code generation times out
- Set timeout for QR Tiger API calls (e.g., 10 seconds)
- If timeout occurs, proceed without QR code
- Implement retry mechanism with exponential backoff
Scenario 3: Invalid playback URL
- Validate playback URL format before sending to QR Tiger
- Ensure URL is reachable and returns 200 OK
- Use URL validation library
QR Code Specifications
Technical Requirements
- Size: 500x500px (optimized for printing)
- Format: PNG with transparent background
- Error Correction: High (H) - 30% damage tolerance
- DPI: 300 DPI minimum for print quality
- Content: Playback URL only (e.g.,
https://micdots.com/play/{slug})
Quality Guidelines
For Physical Printing:
- Minimum size: 2cm x 2cm (0.8" x 0.8")
- Recommended size: 3-5cm x 3-5cm (1.2"-2" x 1.2"-2")
- Maintain high contrast (dark QR on light background)
- Test scanning before mass printing
For Digital Use:
- Display at least 200x200px on screen
- Ensure sufficient contrast for screens
- Test on multiple devices
Testing
Manual Testing Checklist
QR Code Generation:
- QR code is generated for each submission
- QR code URL is returned in API response
- QR code image is accessible via S3 URL
- QR code filename matches audio slug
QR Code Functionality:
- QR code scans correctly on iOS devices
- QR code scans correctly on Android devices
- QR code redirects to correct playback page
- QR code works after printing (print test)
- Damaged QR code still works (30% error correction)
Integration:
- Audio and QR generation succeed together
- If QR generation fails, audio still works
- Processing time is acceptable (less than 10 seconds)
- QR code download button works on result page
Test QR Code Generation
# Test QR Tiger API directly
curl -X POST "https://api.qrtiger.com/v1/qr" \
-H "Authorization: Bearer {your-api-key}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://micdots.com/play/test-slug-123",
"size": 500,
"format": "png",
"errorCorrection": "H"
}'
Performance Considerations
Processing Time
Epic 1 (Audio Only):
- ElevenLabs API: ~2-5 seconds
- S3 upload: ~0.5-1 second
- Total: ~3-6 seconds
Epic 2 (Audio + QR):
- ElevenLabs API: ~2-5 seconds
- Audio S3 upload: ~0.5-1 second
- QR Tiger API: ~1-2 seconds
- QR image download: ~0.5 second
- QR S3 upload: ~0.5-1 second
- Total: ~5-10 seconds
Optimization Tips
- Parallel Processing: Generate QR code while uploading audio to S3
- Caching: Cache QR Tiger API responses for duplicate URLs
- CDN: Use CloudFront CDN for faster QR image delivery
- Async Processing: Move QR generation to background job if time exceeds 10 seconds
Security Considerations
API Key Management
- Store QR Tiger API key in environment variables (never in code)
- Rotate API keys periodically (every 90 days)
- Use separate API keys for dev/staging/production
- Monitor API key usage for anomalies
QR Code Content
- Validate all URLs before generating QR codes
- Ensure QR codes only point to micdots.com domain
- Prevent QR code generation for malicious URLs
- Implement URL whitelist for QR code generation
Rate Limiting
- Implement rate limiting for QR code generation (10/minute per user)
- Monitor QR Tiger API usage to avoid unexpected costs
- Cache generated QR codes to reduce API calls
Cost Considerations
QR Tiger Pricing
QR Tiger pricing varies by plan:
- Free Plan: Limited QR codes per month
- Paid Plans: Unlimited QR codes with higher API limits
Recommendation: Start with paid plan for production to ensure reliability.
Cost Optimization
- Cache QR codes: Don't regenerate for same playback URL
- Batch processing: Generate QR codes in batches if possible
- Monitor usage: Track monthly QR generation counts
- Implement limits: Set per-user QR generation limits
Related Documentation
- Text-to-Speech Submission API - Epic 1 audio generation
- Epic 2 Overview - QR code generation feature overview
- Result Page UI - Where QR codes are displayed
- AWS S3 Storage - S3 configuration details
Migration from Epic 1
Database Schema Updates
Add qrCodeUrl column to submissions table:
ALTER TABLE text_to_speech_submissions
ADD COLUMN qr_code_url VARCHAR(500) NULL;
Backwards Compatibility
- Submissions created in Epic 1 will have
qrCodeUrl: null - Epic 2 code should handle null QR code URLs gracefully
- Frontend should hide QR code section if URL is null
Regenerating QR Codes for Epic 1 Submissions
Optional: Create a script to generate QR codes for existing submissions:
async function backfillQRCodes() {
const submissions = await database.getSubmissionsWithoutQR();
for (const submission of submissions) {
try {
const playbackUrl = `https://micdots.com/play/${submission.slug}`;
const qrCodeUrl = await generateAndUploadQRCode(
playbackUrl,
submission.slug
);
await database.updateSubmission(submission.id, { qrCodeUrl });
console.log(`Generated QR for ${submission.slug}`);
} catch (error) {
console.error(`Failed to generate QR for ${submission.slug}:`, error);
}
}
}
Troubleshooting
QR Code Not Generating
Issue: QR Tiger API returns error Solution:
- Check API key is valid and not expired
- Verify API rate limits haven't been exceeded
- Ensure playback URL is valid and accessible
- Check QR Tiger service status
QR Code Not Scanning
Issue: Mobile devices can't scan QR code Solution:
- Verify error correction level is set to "H"
- Increase QR code size to at least 500x500px
- Ensure sufficient contrast in printed version
- Test with multiple QR code scanner apps
S3 Upload Fails
Issue: QR code image won't upload to S3 Solution:
- Verify S3 bucket exists and has correct permissions
- Check S3 credentials and IAM policies
- Ensure bucket is in correct region (us-east-1)
- Verify image buffer is not empty
Future Enhancements (Not in Epic 2)
The following features are planned for future releases but are NOT included in Epic 2:
- Custom QR code branding and colors
- QR code analytics (scan tracking)
- QR code expiration dates
- QR code customization (logo overlay)
- Bulk QR code generation
- QR code templates for different use cases
- Alternative export formats (only PNG is supported)