Event Tickets Example
Issue and manage event tickets with check-in tracking.
Setup
typescript
import { WalletHero } from '@wallethero/sdk';
const client = new WalletHero({
apiToken: process.env.WALLETHERO_API_TOKEN!
});
const WORKSPACE_ID = 'your-workspace-id';
const PROJECT_ID = 'your-project-id';1. Create Event Template
typescript
const concertTemplate = await client.passTemplates.create({
name: 'Summer Concert 2024',
workspace_id: WORKSPACE_ID,
project_id: PROJECT_ID,
apple_pass_type_identifier: 'pass.com.example.events',
background_color: '#1a1a2e',
label_color: '#e94560',
value_color: '#ffffff',
logo_text: 'SUMMER FEST',
barcode_type: 'qr',
barcode_id: 'id', // Use pass ID as barcode
top_field_label: 'SECTION',
top_field_value: '{{section}}',
front_fields: [
{ label: 'Date', value: '{{event_date}}' },
{ label: 'Time', value: '{{event_time}}' },
{ label: 'Seat', value: '{{seat}}' }
],
secondary_fields: [
{ label: 'Guest', value: '{{full_name}}' }
],
back_fields: [
{ label: 'Venue', value: 'Central Park Arena' },
{ label: 'Address', value: '123 Park Ave, New York, NY' },
{ label: 'Terms', value: 'No refunds. Must present valid ID.' }
],
locations: [
{
latitude: 40.7829,
longitude: -73.9654,
name: 'Central Park Arena'
}
],
location_message: 'Welcome to Summer Fest!'
});
// Upload event artwork
await client.passTemplates.uploadCoverImage(
concertTemplate.id,
eventBannerFile
);2. Issue Tickets
typescript
interface TicketOrder {
name: string;
email: string;
section: string;
row: string;
seat: string;
ticketType: 'GA' | 'VIP' | 'Premium';
}
async function issueTicket(order: TicketOrder) {
const ticket = await client.passes.create({
pass_template_id: concertTemplate.id,
project_id: PROJECT_ID,
workspace_id: WORKSPACE_ID,
full_name: order.name,
email: order.email,
custom_fields: {
section: order.section,
row: order.row,
seat: order.seat,
ticket_type: order.ticketType,
event_date: 'July 15, 2024',
event_time: '7:00 PM',
checked_in: false,
order_id: `ORD-${Date.now()}`
}
});
// Record ticket purchase event
await client.events.create({
pass_id: ticket.id,
event_category: 'activity',
event_type: 'custom',
metadata: {
action: 'ticket_purchased',
ticket_type: order.ticketType,
section: order.section
}
});
return ticket;
}
// Issue tickets for an order
const tickets = await Promise.all([
issueTicket({
name: 'John Doe',
email: '[email protected]',
section: 'A',
row: '5',
seat: '12',
ticketType: 'VIP'
}),
issueTicket({
name: 'Jane Doe',
email: '[email protected]',
section: 'A',
row: '5',
seat: '13',
ticketType: 'VIP'
})
]);
console.log('Tickets issued:');
tickets.forEach(t => {
console.log(`- ${t.full_name}: ${t.apple_pass_url}`);
});3. Check-In System
typescript
async function checkIn(passId: string, gate: string) {
const pass = await client.passes.get(passId);
// Check if already checked in
if (pass.custom_fields?.checked_in) {
return {
success: false,
error: 'Already checked in',
checkedInAt: pass.custom_fields.checked_in_at
};
}
// Record check-in
await client.events.recordCheckIn(passId, {
source: gate,
metadata: {
gate,
section: pass.custom_fields?.section
}
});
// Update pass status
await client.passes.update(passId, {
notification: 'Welcome! Enjoy the show!',
custom_fields: {
checked_in: true,
checked_in_at: new Date().toISOString(),
checked_in_gate: gate
}
});
return {
success: true,
guest: pass.full_name,
section: pass.custom_fields?.section,
seat: pass.custom_fields?.seat
};
}
// Simulate scanning a ticket
const result = await checkIn('ticket-pass-id', 'Gate A');
if (result.success) {
console.log(`✓ Checked in ${result.guest} - Section ${result.section}, Seat ${result.seat}`);
} else {
console.log(`✗ ${result.error}`);
}4. Real-Time Updates
typescript
// Send reminder before event
async function sendEventReminder() {
// Get all tickets for tomorrow's event
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const tickets = await client.passes.list({
filter: {
pass_template_id: { _eq: concertTemplate.id },
custom_fields: {
checked_in: { _eq: false }
}
}
});
// Send reminder to each
for (const ticket of tickets) {
await client.passes.update(ticket.id, {
notification: '🎵 See you tomorrow! Doors open at 6 PM.'
});
}
console.log(`Sent reminders to ${tickets.length} ticket holders`);
}
// Send last-minute gate change
async function announceGateChange(section: string, newGate: string) {
const affected = await client.passes.list({
filter: {
pass_template_id: { _eq: concertTemplate.id },
custom_fields: {
section: { _eq: section }
}
}
});
for (const ticket of affected) {
await client.passes.update(ticket.id, {
notification: `Gate change! Section ${section} now enters via ${newGate}.`,
custom_fields: {
entry_gate: newGate
}
});
}
console.log(`Notified ${affected.length} guests in Section ${section}`);
}5. Analytics
typescript
// Get check-in statistics
async function getCheckInStats() {
const total = await client.passes.list({
filter: { pass_template_id: { _eq: concertTemplate.id } }
});
const checkedIn = total.filter(p => p.custom_fields?.checked_in);
// Check-ins by gate
const checkIns = await client.events.list({
workspace_id: WORKSPACE_ID,
event_category: 'activity'
});
const byGate = checkIns.reduce((acc, e) => {
const gate = e.metadata?.gate || 'Unknown';
acc[gate] = (acc[gate] || 0) + 1;
return acc;
}, {} as Record<string, number>);
return {
totalTickets: total.length,
checkedIn: checkedIn.length,
remaining: total.length - checkedIn.length,
byGate
};
}
const stats = await getCheckInStats();
console.log(`Check-in Status:`);
console.log(` Total: ${stats.totalTickets}`);
console.log(` Checked In: ${stats.checkedIn} (${(stats.checkedIn/stats.totalTickets*100).toFixed(1)}%)`);
console.log(` Remaining: ${stats.remaining}`);
console.log(` By Gate:`, stats.byGate);