Installation
npm install ticketnation-sdk
Requires Node.js 18+ (uses native fetch). TypeScript 5.0+ recommended.
Initialization
import { Ticketnation } from 'ticketnation-sdk';
const tn = new Ticketnation({
apiKey: process.env.TICKETNATION_API_KEY!, // Required — never hardcode!
baseUrl: 'http://localhost:4000', // Default: https://api.ticketnation.ph
timeout: 30000, // Default: 30s
retries: 2, // Default: 2 retries on 5xx
debug: false, // Logs requests with redacted key
});
Never hardcode your API key. Store it in an environment variable (TICKETNATION_API_KEY) and load it at runtime. Add .env to your .gitignore to prevent accidental commits.
tn.me()
Get API key and organization info.
const info = await tn.me();
// Returns: AccountInfo
// {
// apiKey: { id, name, scopes, callbackUrl, createdAt, expiresAt, lastUsedAt },
// organization: { id, name, slug }
// }
tn.events
create(params)
Creates an event in DRAFT status. Optionally include inline ticket types.
const event = await tn.events.create({
name: 'Summer Fest', // required
dateTime: '2025-06-15T18:00:00.000Z', // required
endDateTime: '2025-06-15T23:00:00.000Z',
venueId: 'uuid',
type: 'PAID', // 'PAID' | 'FREE'
journeyType: 'STANDARD', // 'STANDARD' | 'RSVP' | 'PRESELLING'
visibility: 'PUBLIC', // 'PUBLIC' | 'PRIVATE'
imageUrl: 'https://example.com/cover.jpg',
galleryUrls: [
'https://example.com/gallery-1.jpg',
'https://example.com/gallery-2.jpg',
],
absorbFees: true, // default: true
timezone: 'Asia/Manila', // default: 'Asia/Manila'
currency: 'PHP', // default: 'PHP'
eventCapacity: 1000,
callbackUrl: 'https://api.example.com/webhooks',
tickets: [ // optional inline tickets
{ name: 'GA', price: 1500, quantity: 500, published: true },
],
});
// Returns: Event (status: 'DRAFT')
createAndPublish(params)
Creates an event and immediately publishes it to the marketplace in a single call. Accepts the same parameters as create().
const event = await tn.events.createAndPublish({
name: 'Summer Fest',
dateTime: '2025-06-15T18:00:00.000Z',
tickets: [
{ name: 'GA', price: 1500, quantity: 500, published: true },
],
});
// Returns: Event (status: 'PUBLISHED')
console.log(event.status); // 'PUBLISHED'
Use createAndPublish() when you want events to go live immediately. Use create() + publish() separately when you need a review step before going live.
list(params?)
const { data, meta } = await tn.events.list({
page: 1,
take: 10,
status: 'PUBLISHED', // 'DRAFT' | 'PUBLISHED' | 'ARCHIVED'
search: 'summer',
});
// Returns: PaginatedResponse<Event>
get(idOrSlug)
const event = await tn.events.get('summer-fest-2025');
// or
const event = await tn.events.get('uuid-event-id');
// Returns: Event
update(eventId, params)
const event = await tn.events.update(eventId, {
name: 'Updated Name',
eventCapacity: 2000,
imageUrl: 'https://example.com/new-cover.jpg',
galleryUrls: ['https://example.com/new-gallery.jpg'],
});
// Returns: Event
publish(eventId) / unpublish(eventId) / archive(eventId)
const event = await tn.events.publish(eventId);
const event = await tn.events.unpublish(eventId);
const event = await tn.events.archive(eventId);
// Returns: Event
delete(eventId)
Only works on DRAFT events with no sold tickets.
const result = await tn.events.delete(eventId);
// Returns: { deleted: true, id: 'uuid' }
tn.tickets
create(eventId, params)
const ticket = await tn.tickets.create(eventId, {
name: 'VIP Pass', // required
price: 5000, // required, in whole pesos (₱5,000.00)
quantity: 100, // required
section: 'VIP Section',
row: 'A',
type: 'VIP', // 'GENERAL_ADMISSION' | 'RESERVED_SEAT' | 'VIP'
maximumPurchaseQuantity: 4,
published: true,
});
// Returns: Ticket
list(eventId)
const tickets = await tn.tickets.list(eventId);
// Returns: Ticket[]
get(eventId, ticketId)
const ticket = await tn.tickets.get(eventId, ticketId);
// Returns: Ticket
update(eventId, ticketId, params)
const ticket = await tn.tickets.update(eventId, ticketId, {
price: 4500,
quantity: 150,
});
// Returns: Ticket
publish(eventId, ticketId)
const ticket = await tn.tickets.publish(eventId, ticketId);
// Returns: Ticket
markSoldOut(eventId, ticketId)
Sets remainingQuantity to 0.
const ticket = await tn.tickets.markSoldOut(eventId, ticketId);
// Returns: Ticket (with remainingQuantity: 0)
delete(eventId, ticketId)
Only works if no tickets have been sold.
const result = await tn.tickets.delete(eventId, ticketId);
// Returns: { deleted: true, id: 'uuid' }
Manage the performer lineup for an event. Requires events:write scope for mutations, events:read for listing.
create(eventId, params)
const performer = await tn.performers.create(eventId, {
name: 'SB19', // required
type: 'ARTIST', // optional
imageUrl: 'https://example.com/sb19.jpg', // optional
description: 'P-pop icons', // optional
});
// Returns: Performer
// { id, name, type, imageUrl, description, eventId, createdAt }
list(eventId)
const performers = await tn.performers.list(eventId);
// Returns: Performer[]
const result = await tn.performers.remove(eventId, performerId);
// Returns: { deleted: true, id: 'uuid' }
Full example — building a lineup:
// Add all performers
const headliner = await tn.performers.create(eventId, {
name: 'SB19',
type: 'ARTIST',
imageUrl: 'https://example.com/sb19.jpg',
description: 'P-pop icons',
});
const dj = await tn.performers.create(eventId, {
name: 'DJ Nix',
type: 'DJ',
});
const host = await tn.performers.create(eventId, {
name: 'Vice Ganda',
type: 'HOST',
description: 'Event host and comedian',
});
// List the lineup
const lineup = await tn.performers.list(eventId);
console.log(`${lineup.length} performers on the bill`);
// Remove a performer if plans change
await tn.performers.remove(eventId, dj.id);
tn.schedules
Build a timetable for your event. Schedule entries can optionally link to performers. Requires events:write scope for mutations, events:read for listing.
create(eventId, params)
const entry = await tn.schedules.create(eventId, {
title: 'SB19 Live', // required
startTime: '2025-06-15T20:00:00.000Z', // required
endTime: '2025-06-15T22:30:00.000Z', // required
description: 'Main stage performance', // optional
icon: 'microphone', // optional
color: '#1DB954', // optional
performerId: 'uuid-performer-id', // optional
});
// Returns: Schedule
// { id, title, startTime, endTime, description, icon, color, performerId, eventId, createdAt }
list(eventId)
const schedule = await tn.schedules.list(eventId);
// Returns: Schedule[]
update(eventId, scheduleId, params)
const entry = await tn.schedules.update(eventId, scheduleId, {
title: 'SB19 Main Set (Extended)',
endTime: '2025-06-15T23:00:00.000Z',
});
// Returns: Schedule
remove(eventId, scheduleId)
const result = await tn.schedules.remove(eventId, scheduleId);
// Returns: { deleted: true, id: 'uuid' }
Full example — building a timetable:
// Create performers first
const sb19 = await tn.performers.create(eventId, {
name: 'SB19',
type: 'ARTIST',
});
const djNix = await tn.performers.create(eventId, {
name: 'DJ Nix',
type: 'DJ',
});
// Build the schedule
await tn.schedules.create(eventId, {
title: 'Doors Open',
startTime: '2025-06-15T17:00:00.000Z',
endTime: '2025-06-15T18:00:00.000Z',
icon: 'door',
});
await tn.schedules.create(eventId, {
title: 'DJ Nix Warm-Up Set',
startTime: '2025-06-15T18:00:00.000Z',
endTime: '2025-06-15T19:30:00.000Z',
performerId: djNix.id,
color: '#FF6B35',
});
await tn.schedules.create(eventId, {
title: 'SB19 Live',
startTime: '2025-06-15T20:00:00.000Z',
endTime: '2025-06-15T22:30:00.000Z',
performerId: sb19.id,
description: 'Main stage headline set',
color: '#1DB954',
});
// Update if timing changes
const schedule = await tn.schedules.list(eventId);
const sb19Set = schedule.find((s) => s.title === 'SB19 Live');
if (sb19Set) {
await tn.schedules.update(eventId, sb19Set.id, {
endTime: '2025-06-15T23:00:00.000Z',
});
}
tn.brands
Attach sponsor or partner brands to your event. Requires events:write scope for mutations, events:read for listing.
create(eventId, params)
const brand = await tn.brands.create(eventId, {
name: 'Red Bull', // required
url: 'https://redbull.com', // optional
imageUrl: 'https://example.com/redbull.png', // optional
description: 'Energy drink partner', // optional
});
// Returns: Brand
// { id, name, url, imageUrl, description, eventId, createdAt }
list(eventId)
const brands = await tn.brands.list(eventId);
// Returns: Brand[]
remove(eventId, brandId)
const result = await tn.brands.remove(eventId, brandId);
// Returns: { deleted: true, id: 'uuid' }
Full example — attaching sponsors:
await tn.brands.create(eventId, {
name: 'Red Bull',
url: 'https://redbull.com',
imageUrl: 'https://example.com/redbull.png',
description: 'Energy drink partner',
});
await tn.brands.create(eventId, {
name: 'Globe Telecom',
url: 'https://globe.com.ph',
imageUrl: 'https://example.com/globe.png',
description: 'Presenting sponsor',
});
await tn.brands.create(eventId, {
name: 'Jollibee',
imageUrl: 'https://example.com/jollibee.png',
description: 'Official food partner',
});
// List all brands
const brands = await tn.brands.list(eventId);
console.log(`${brands.length} sponsors attached`);
tn.orders
Orders are read-only. Requires orders:read scope.
list(eventId, params?)
const { data, meta } = await tn.orders.list(eventId, {
page: 1,
take: 20,
status: 'COMPLETED', // 'PENDING' | 'COMPLETED' | 'CANCELLED' | 'REFUNDED'
});
// Returns: PaginatedResponse<Order>
get(orderId)
Includes payment details.
const order = await tn.orders.get(orderId);
// Returns: Order (with payment info)
tn.venues
search(params)
const { data, meta } = await tn.venues.search({
query: 'MOA Arena', // required
page: 1,
take: 10,
});
// Returns: PaginatedResponse<Venue>
tn.webhooks
create(params)
Returns the webhook with a secret field — store it securely, it is only shown once.
const webhook = await tn.webhooks.create({
url: 'https://api.example.com/webhooks/ticketnation',
events: ['order.completed', 'event.sold_out'],
});
console.log(webhook.secret); // whsec_...
// Returns: WebhookWithSecret
list()
const webhooks = await tn.webhooks.list();
// Returns: Webhook[]
update(webhookId, params)
const webhook = await tn.webhooks.update(webhookId, {
events: ['order.completed'],
isActive: true,
});
// Returns: Webhook
delete(webhookId)
const result = await tn.webhooks.delete(webhookId);
// Returns: { deleted: true, id: 'uuid' }
test(webhookId)
Sends a test payload to your webhook URL.
const result = await tn.webhooks.test(webhookId);
// Returns: { success: true, statusCode: 200, message: '...' }
deliveries(webhookId, params?)
View delivery history for a webhook.
const { data, meta } = await tn.webhooks.deliveries(webhookId, {
page: 1,
take: 20,
});
// Returns: PaginatedResponse<WebhookDelivery>
Utilities
The SDK exports helper functions for common tasks.
Formats a number as a Philippine Peso string. Returns "Free" for zero.
import { formatPeso } from 'ticketnation-sdk';
formatPeso(1500); // "₱1,500.00"
formatPeso(0); // "Free"
formatPeso(99); // "₱99.00"
validatePrice(price)
Validates that a price is a valid number. Throws a TicketnationError if invalid.
import { validatePrice } from 'ticketnation-sdk';
validatePrice(1500); // OK — no error
validatePrice(-100); // Throws TicketnationError
validatePrice(NaN); // Throws TicketnationError
paginate()
Async generator that yields one page at a time:
import { paginate } from 'ticketnation-sdk';
for await (const batch of paginate((p) => tn.events.list(p))) {
for (const event of batch) {
console.log(event.name);
}
}
fetchAllPages()
Collects all pages into a single array:
import { fetchAllPages } from 'ticketnation-sdk';
const allEvents = await fetchAllPages((p) => tn.events.list(p));
console.log(`Total: ${allEvents.length} events`);
fetchAllPages() loads everything into memory. For large datasets, prefer paginate() which streams one page at a time.
Error Handling
All API errors throw TicketnationError with a hint property that provides actionable guidance:
import { TicketnationError } from 'ticketnation-sdk';
try {
await tn.events.get('nonexistent');
} catch (error) {
if (error instanceof TicketnationError) {
error.code; // 'NOT_FOUND'
error.status; // 404
error.message; // 'Event not found: nonexistent'
error.requestId; // 'req_a1b2c3d4' — for support tickets
error.details; // Array of field errors (for VALIDATION_ERROR)
error.hint; // 'Check that the event ID is correct and belongs to your organization.'
}
}
The error.hint property gives you a human-readable suggestion for how to fix the error. It is especially useful for SCOPE_REQUIRED and VALIDATION_ERROR responses.
Error handling with hints:
try {
await tn.events.create({ name: '' });
} catch (error) {
if (error instanceof TicketnationError) {
console.log(`Error: ${error.message}`);
if (error.hint) {
console.log(`Hint: ${error.hint}`);
// e.g., "The 'name' field is required and cannot be empty."
}
if (error.details) {
console.log('Field errors:', error.details);
}
}
}
See the Error Handling page for the complete list of error codes and troubleshooting tips.
TypeScript Types
All types are exported from the package:
import type {
// Core resources
Event,
Ticket,
Order,
Venue,
Performer,
Schedule,
Brand,
Webhook,
WebhookWithSecret,
WebhookDelivery,
WebhookTestResult,
AccountInfo,
DeletedResponse,
// Create/update params
CreateEventParams,
CreateTicketParams,
CreateWebhookParams,
UpdateWebhookParams,
CreatePerformerParams,
CreateScheduleParams,
UpdateScheduleParams,
CreateBrandParams,
// List/search params
ListEventsParams,
ListOrdersParams,
SearchVenuesParams,
// Pagination
PaginatedResponse,
// Config and errors
TicketnationConfig,
TicketnationError,
} from 'ticketnation-sdk';
Key Type Definitions
interface CreateEventParams {
name: string; // required
dateTime: string; // required, ISO 8601
endDateTime?: string;
type?: 'PAID' | 'FREE';
journeyType?: 'STANDARD' | 'RSVP' | 'PRESELLING';
venueId?: string;
imageUrl?: string;
galleryUrls?: string[];
absorbFees?: boolean; // default: true
timezone?: string; // default: 'Asia/Manila'
currency?: string; // default: 'PHP'
visibility?: 'PUBLIC' | 'PRIVATE';
callbackUrl?: string;
eventCapacity?: number;
description?: string;
tickets?: CreateTicketParams[];
}
interface CreatePerformerParams {
name: string; // required
type?: string;
imageUrl?: string;
description?: string;
}
interface CreateScheduleParams {
title: string; // required
startTime: string; // required, ISO 8601
endTime: string; // required, ISO 8601
description?: string;
icon?: string;
color?: string;
performerId?: string;
}
interface CreateBrandParams {
name: string; // required
url?: string;
imageUrl?: string;
description?: string;
}