Event Ticket Image Generation: QR Codes + Dynamic Data
We sold 1,847 tickets to our conference last year. Each one needed a ticket with the attendee's name, their ticket type, a unique QR code for check-in, and event details.
I spent our entire budget on a ticketing platform that did this automatically. It worked, but we paid 5% + $2.50 per ticket. For our event, that was $12,000 in fees.
This year, we built our own ticketing with an image generation API. Same professional tickets, QR codes included. Total cost: $47 for the month. Attendees got better-looking tickets, and we saved enough to upgrade the catering.
Here's how to generate event tickets without paying massive platform fees.
Why generate event tickets with an apiWhy Generate Event Tickets with an API
Ticketing platforms like Eventbrite and Ticketmaster make it easy, but you pay for that convenience. Platform fees eat 5-15% of every ticket sale.
If you're handling registration yourself (through your website, Stripe, or a custom system), you just need to generate the actual ticket images. That's where APIs come in.
What you control when you generate tickets:
- Complete design freedom (your brand, your style)
- No per-ticket fees (pay for API calls, not sales percentage)
- Custom data fields (add whatever information you need)
- Direct attendee relationships (they're your customers, not the platform's)
You still need a way to check people in at the door, but that's simpler than it sounds.
What goes on an event ticketWhat Goes on an Event Ticket
Event tickets need enough information to get someone through the door.
Essential elements:
- Event name and date
- Attendee name
- Ticket type (General Admission, VIP, Speaker, etc.)
- QR code (for check-in)
- Ticket ID (unique identifier)
- Venue name and address
Optional but useful:
- Seat or table number (for assigned seating)
- Event logo and branding
- Start time and doors open time
- Special instructions (parking, dress code)
- Schedule or agenda (for multi-day events)
Keep it scannable. People glance at tickets quickly to confirm details, then show the QR code at the door.
Common event typesCommon Event Types
Ticket automation works for any event where people need proof of registration.
Conferences and workshopsConferences and Workshops
Multi-day events with different ticket tiers. Attendees need to prove they have access.
Key ticket elements:
- Attendee name and company
- Ticket type (Early Bird, Standard, VIP)
- Days they have access to
- QR code for daily check-in
- Unique ticket ID
For large conferences, you might generate badge inserts instead of traditional tickets. Same concept, different format.
Concerts and festivalsConcerts and Festivals
Music events need tickets that handle general admission and assigned seating.
Key ticket elements:
- Artist or lineup information
- Date and venue
- Section, row, and seat (if assigned)
- QR code for entry
- Age restrictions if applicable
For festivals with multiple stages, include a map or stage lineup on the ticket back.
Networking events and meetupsNetworking Events and Meetups
Smaller professional events still benefit from proper ticketing.
Key ticket elements:
- Event name and organizer
- Date, time, and location
- Attendee name and title
- Ticket type (Member, Guest, Speaker)
- QR code for check-in
These events often use tickets as name badges. Design accordingly.
Webinars and virtual eventsWebinars and Virtual Events
Even online events need tickets—they're access credentials.
Key ticket elements:
- Event name and date
- Attendee email (for verification)
- Access link or meeting ID
- Time zone and start time
- Unique ticket ID (to prevent sharing)
Virtual event tickets can include QR codes that link directly to the event join page.
Sports and recreationSports and Recreation
Leagues, tournaments, and recreational events need ticketing for spectators and participants.
Key ticket elements:
- Game or match details
- Teams playing
- Seat or section
- Date and time
- Venue name
Season pass holders might get a single ticket valid for multiple games, with a QR code that works all season.
How to set up ticket generationHow to Set Up Ticket Generation
The technical flow is straightforward: purchase → generate ticket → send to attendee.
Step 1 design your ticket templateStep 1: Design Your Ticket Template
Create a professional ticket design that matches your event branding.
Design considerations:
- Readable at a glance (people check tickets quickly)
- Space for QR code (needs to be scannable)
- Clear hierarchy (name and event should be most prominent)
- Professional but event-appropriate (formal for conferences, fun for festivals)
In Imejis.io, create your ticket layout and mark all attendee-specific fields as editable (name, ticket type, seat, QR code, etc.).
Step 2 generate unique ticket ids and qr codesStep 2: Generate Unique Ticket IDs and QR Codes
Every ticket needs a unique ID. When someone buys a ticket, generate an ID and create a QR code from it.
const crypto = require("crypto")
const QRCode = require("qrcode")
// Generate unique ticket ID
const ticketId = `TKT-${Date.now()}-${crypto.randomBytes(4).toString("hex")}`
// Generate QR code image
const qrCodeUrl = await QRCode.toDataURL(ticketId)The QR code encodes the ticket ID. When scanned at check-in, your system looks up the ticket and marks it as used.
Step 3 call the ticket generation apiStep 3: Call the Ticket Generation API
Once you have the attendee data and QR code, generate the ticket image.
curl -X POST "https://render.imejis.io/v1/YOUR_TEMPLATE_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_name": "DevConf 2026",
"attendee_name": "Sarah Johnson",
"ticket_type": "VIP Pass",
"date": "March 15-17, 2026",
"venue": "Convention Center Hall A",
"ticket_id": "TKT-1708032847-a3f8e2c1",
"qr_code_url": "data:image/png;base64,iVBORw0KG..."
}'The API returns the ticket image in seconds. Send it to the attendee immediately.
Step 4 deliver tickets to attendeesStep 4: Deliver Tickets to Attendees
Most events send tickets via email as PDF or image attachments. Some offer in-app tickets through Apple Wallet or Google Pay.
// Email ticket as attachment
await sendTicketEmail({
to: attendee.email,
subject: "Your DevConf 2026 Ticket",
attachments: [
{
filename: `ticket-${ticketId}.png`,
content: ticketImage,
},
],
})Code examplesCode Examples
Here's how to implement ticket generation in different environments.
Nodejs complete flowNode.js (Complete Flow)
const axios = require("axios")
const QRCode = require("qrcode")
const crypto = require("crypto")
const nodemailer = require("nodemailer")
async function processTicketPurchase(order) {
const tickets = []
// Generate tickets for each attendee
for (const attendee of order.attendees) {
const ticket = await generateTicket({
eventName: order.event.name,
attendeeName: attendee.name,
ticketType: attendee.ticketType,
date: order.event.date,
venue: order.event.venue,
orderId: order.id,
})
tickets.push(ticket)
}
// Email all tickets
await emailTickets(order.email, tickets)
return tickets
}
async function generateTicket(data) {
// Generate unique ticket ID
const ticketId = `TKT-${Date.now()}-${crypto.randomBytes(4).toString("hex")}`
// Generate QR code
const qrCodeUrl = await QRCode.toDataURL(ticketId)
// Generate ticket image
const response = await axios({
method: "post",
url: "https://render.imejis.io/v1/YOUR_TEMPLATE_ID",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
data: {
event_name: data.eventName,
attendee_name: data.attendeeName,
ticket_type: data.ticketType,
date: data.date,
venue: data.venue,
ticket_id: ticketId,
qr_code_url: qrCodeUrl,
},
responseType: "arraybuffer",
})
// Save to database
await saveTicket({
ticketId,
orderId: data.orderId,
attendeeName: data.attendeeName,
used: false,
})
return {
id: ticketId,
image: response.data,
}
}
async function emailTickets(email, tickets) {
const transporter = nodemailer.createTransport({
/* config */
})
const attachments = tickets.map((ticket) => ({
filename: `ticket-${ticket.id}.png`,
content: ticket.image,
}))
await transporter.sendMail({
to: email,
subject: "Your Event Tickets",
html: "<p>Your tickets are attached. See you at the event!</p>",
attachments,
})
}Python with flaskPython with Flask
import qrcode
import io
import base64
import requests
from datetime import datetime
import secrets
def generate_ticket(attendee, event):
# Generate ticket ID
ticket_id = f"TKT-{int(datetime.now().timestamp())}-{secrets.token_hex(4)}"
# Generate QR code
qr = qrcode.QRCode(version=1, box_size=10, border=2)
qr.add_data(ticket_id)
qr.make(fit=True)
qr_image = qr.make_image(fill_color="black", back_color="white")
buffer = io.BytesIO()
qr_image.save(buffer, format='PNG')
qr_base64 = base64.b64encode(buffer.getvalue()).decode()
qr_data_url = f"data:image/png;base64,{qr_base64}"
# Generate ticket image
response = requests.post(
'https://render.imejis.io/v1/YOUR_TEMPLATE_ID',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'event_name': event['name'],
'attendee_name': attendee['name'],
'ticket_type': attendee['ticket_type'],
'date': event['date'],
'venue': event['venue'],
'ticket_id': ticket_id,
'qr_code_url': qr_data_url
}
)
# Save ticket to database
save_ticket_to_db(ticket_id, attendee['id'], False)
return {
'id': ticket_id,
'image': response.content
}
def process_order(order):
tickets = []
for attendee in order['attendees']:
ticket = generate_ticket(attendee, order['event'])
tickets.append(ticket)
# Email tickets
send_ticket_email(order['email'], tickets)
return ticketsPhp for wordpress eventsPHP for WordPress Events
<?php
require_once 'vendor/autoload.php';
use Endroid\QrCode\QrCode;
function generate_event_ticket($attendee, $event) {
// Generate ticket ID
$ticket_id = 'TKT-' . time() . '-' . bin2hex(random_bytes(4));
// Generate QR code
$qrCode = new QrCode($ticket_id);
$qr_image = $qrCode->writeString();
$qr_base64 = base64_encode($qr_image);
$qr_data_url = 'data:image/png;base64,' . $qr_base64;
// Generate ticket image
$response = wp_remote_post('https://render.imejis.io/v1/YOUR_TEMPLATE_ID', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY',
'Content-Type' => 'application/json'
],
'body' => json_encode([
'event_name' => $event['name'],
'attendee_name' => $attendee['name'],
'ticket_type' => $attendee['ticket_type'],
'date' => $event['date'],
'venue' => $event['venue'],
'ticket_id' => $ticket_id,
'qr_code_url' => $qr_data_url
]),
'timeout' => 15
]);
if (!is_wp_error($response)) {
$ticket_image = wp_remote_retrieve_body($response);
// Save to database
save_ticket_to_database($ticket_id, $attendee['id'], $ticket_image);
return [
'id' => $ticket_id,
'image' => $ticket_image
];
}
return false;
}
// Hook into WooCommerce order completion
add_action('woocommerce_order_status_completed', function($order_id) {
$order = wc_get_order($order_id);
$tickets = [];
// Generate tickets for each attendee
foreach ($order->get_items() as $item) {
$attendee = get_attendee_data($item);
$event = get_event_data($item);
$ticket = generate_event_ticket($attendee, $event);
if ($ticket) {
$tickets[] = $ticket;
}
}
// Email tickets
email_tickets($order->get_billing_email(), $tickets);
});
?>Template design best practicesTemplate Design Best Practices
Your ticket template affects how professional your event looks.
Make qr codes scannableMake QR Codes Scannable
QR codes need sufficient size and contrast to scan reliably.
QR code guidelines:
- Minimum 200x200px (300x300px is safer)
- High contrast (black on white is standard)
- Clear space around the code (don't crowd it)
- Test scanning from different distances and lighting
Position the QR code prominently. Check-in staff should find it instantly.
Clear visual hierarchyClear Visual Hierarchy
People glance at tickets quickly. Make important information obvious.
Order of importance:
- Event name (largest text)
- Date and time (very prominent)
- Attendee name (personalized element)
- Ticket type or section (especially if access varies)
- QR code (for check-in)
- Venue and address (smaller but readable)
Include a tear off stub optionalInclude a Tear-Off Stub (Optional)
For physical tickets, some organizers print a perforated stub with basic event info that attendees keep after check-in.
The main ticket has the QR code and full details. The stub has just the event name, date, and seat number.
This works if you're printing tickets for attendees to pick up at will-call.
Match event toneMatch Event Tone
Conference tickets look different from music festival tickets. Design accordingly.
- Corporate events: Clean, professional, lots of white space
- Music festivals: Bold colors, energetic design, artistic elements
- Networking events: Professional but approachable, include company logos
- Sports events: Team colors, action photography, bold typography
Add security featuresAdd Security Features
Help staff spot fake tickets quickly.
- Unique ticket IDs (visible on the ticket)
- Subtle background patterns or watermarks
- Holographic effects (if printing physical tickets)
- Date-specific designs (changes each event)
Check in systemCheck-In System
Generating tickets is half the system. You need a way to scan them at the door.
Build a simple scanner appBuild a Simple Scanner App
You don't need a fancy app. A basic QR code scanner that checks ticket IDs against your database works.
Scanner requirements:
- Reads QR codes from ticket images
- Looks up ticket ID in your database
- Shows attendee name and ticket type
- Marks ticket as "used" after first scan
- Flags duplicate scans
You can build this as a web app that runs on tablets or smartphones. Most devices have built-in camera access for QR scanning.
Use a third party scannerUse a Third-Party Scanner
If you don't want to build your own, several QR scanner apps let you integrate with external databases via webhooks or API calls.
When they scan a code, your API endpoint validates it and returns whether entry should be allowed.
Offline mode importantOffline Mode (Important)
WiFi at venues is often unreliable. Your check-in system needs offline capability.
Solution:
- Sync all valid ticket IDs to devices before the event
- Scanner works offline by checking local database
- Sync used tickets back to server when connection returns
This prevents check-in from grinding to a halt if WiFi drops.
Handling special casesHandling Special Cases
Not every ticket is straightforward.
Multiple ticket typesMultiple Ticket Types
Different ticket tiers might need different designs (or at least different colors).
Create template variants for General Admission, VIP, Speaker, Press, etc. Same layout, different visual treatment.
Group ticketsGroup Tickets
When someone buys 5 tickets, generate 5 separate tickets with different names but the same order ID.
for (const attendee of order.attendees) {
await generateTicket({
attendeeName: attendee.name,
ticketType: attendee.type,
orderId: order.id,
})
}Ticket transfersTicket Transfers
If attendees can transfer tickets to others, regenerate the ticket with the new name.
async function transferTicket(ticketId, newAttendeeName) {
const ticket = await getTicket(ticketId)
// Generate new ticket with updated name
const newTicket = await generateTicket({
...ticket.data,
attendeeName: newAttendeeName,
})
// Email to new attendee
await emailTicket(newAttendee.email, newTicket)
// Mark old ticket as transferred
await markTicketTransferred(ticketId)
}Will call ticketsWill-Call Tickets
Some attendees prefer to pick up printed tickets at the venue. Generate tickets as usual, but print them on-site instead of emailing.
Integration with payment providersIntegration with Payment Providers
Connect ticket generation to your payment flow.
Stripe integrationStripe Integration
When a Stripe payment succeeds, generate tickets automatically.
stripe.webhooks.constructEvent(
req.body,
req.headers["stripe-signature"],
webhookSecret
)
if (event.type === "payment_intent.succeeded") {
const order = await getOrder(event.data.object.metadata.orderId)
await processTicketPurchase(order)
}Paypal integrationPayPal Integration
Similar flow with PayPal webhooks.
if (webhookEvent.event_type === "PAYMENT.CAPTURE.COMPLETED") {
const orderId = webhookEvent.resource.purchase_units[0].reference_id
const order = await getOrder(orderId)
await processTicketPurchase(order)
}Direct checkoutDirect Checkout
If you handle payments directly, generate tickets immediately after successful charge.
Bulk ticket generationBulk Ticket Generation
For comp tickets, staff passes, or pre-sold groups, generate tickets in bulk.
const compTickets = [
{ name: "John Smith", type: "Staff", email: "john@event.com" },
{ name: "Jane Doe", type: "Volunteer", email: "jane@event.com" },
// ... more attendees
]
for (const attendee of compTickets) {
const ticket = await generateTicket({
eventName: "DevConf 2026",
attendeeName: attendee.name,
ticketType: attendee.type,
// ... other details
})
await emailTicket(attendee.email, ticket)
}FaqFAQ
How do i generate unique qr codes for each ticketHow do I generate unique QR codes for each ticket?
Create a unique ticket ID for each purchase, then pass it to a QR code API or library. The resulting QR code image URL goes into your ticket template. Most QR libraries generate codes in milliseconds.
Can i send tickets as email attachments or in appCan I send tickets as email attachments or in-app?
Both work great. Email attachments (PNG or PDF) let attendees save tickets offline. In-app display with Apple Wallet or Google Pay integration offers a smoother mobile experience. Many event organizers offer both options.
What happens if someone loses their ticketWhat happens if someone loses their ticket?
Since tickets generate from your database, you can regenerate them anytime. Attendees request a new copy, you call the API again with their order data, and send a fresh ticket. The QR code stays the same if you use their original ticket ID.
How do i prevent ticket fraud or duplicationHow do I prevent ticket fraud or duplication?
Use unique, one-time-use ticket IDs in QR codes. Track scans in your database. When a ticket is scanned at the door, mark it as used. If someone tries to use the same QR code twice, your check-in system flags it.
Can i update ticket details after sending themCan I update ticket details after sending them?
Yes, but only if the changes don't affect the QR code. You can regenerate tickets with updated venue information, times, or seat assignments. If the ticket ID changes, you'll need to resend new tickets to attendees.
Run events without platform feesRun Events Without Platform Fees
Ticketing platforms charge 5-15% per ticket because they bundle payment processing, ticket generation, and marketing tools together. But if you only need the tickets, you're overpaying.
Build your own ticketing with payment APIs and image generation. Same professional tickets, same smooth attendee experience, 95% lower cost.
Design your ticket template, connect it to your registration flow, and let automation handle the rest. Your attendees get beautiful, scannable tickets. You keep more of your revenue.