Everything you need to integrate Tickitz — step-by-step guides, real code examples, and best practices from our team.
Getting started
Follow these five steps to go from a blank project to a working ticketed event with QR check-in. Takes about 10 minutes.
Sign up at tickitz.io — the free tier never expires and requires no credit card. Once inside, navigate to Settings → API Keys and generate your first key.
Settings → API Keys → Create New Keytzk_test_.env file — never commit it to Gittzk_test_ keys in development and tzk_live_ keys only in production. Live keys process real bookings.The @tickitz/sdk package works in Node.js 18+, Bun, Deno, and all major edge runtimes. Pick your package manager:
$ npm install @tickitz/sdk
$ pnpm add @tickitz/sdk
$ yarn add @tickitz/sdk
$ bun add @tickitz/sdk
fetch API. No polyfills needed. For older Node versions, pass a fetch option to the constructor.Create a single Tickitz instance and reuse it across your application. The client handles retries, rate limit backoff, and request signing automatically.
import { Tickitz } from "@tickitz/sdk"; // Create once — reuse everywhere export const tickitz = new Tickitz({ apiKey: process.env.TICKITZ_API_KEY!, // Optional config timeout: 30_000, // 30s request timeout maxRetries: 2, // auto-retry on 429 / 5xx debug: false, // set true to log all requests });
app.locals.Events start in draft status. Once you've configured tiers and capacity, publish to make them live and accepting bookings.
import { tickitz } from "./lib/tickitz"; // 1. Create the event in draft const event = await tickitz.events.create({ title: "Summer Music Festival 2025", description: "An incredible outdoor festival experience.", startsAt: "2025-07-15T18:00:00Z", endsAt: "2025-07-15T23:00:00Z", location: { venue: "Riverside Amphitheater", city: "Austin", state: "TX", country: "US", }, tiers: [ { name: "General Admission", price: 4999, currency: "USD", quantity: 500 }, { name: "VIP", price: 14999, currency: "USD", quantity: 50 }, ], maxCapacity: 550, tags: ["music", "outdoor"], }); console.log(event.id); // "evt_abc123" console.log(event.status); // "draft" // 2. Publish it — now accepting bookings const live = await tickitz.events.publish(event.id); console.log(live.status); // "published" console.log(live.publishedAt); // "2025-06-01T10:00:00Z"
The full lifecycle: create a customer, book tickets, confirm after payment, then scan QR codes at the door. All in one flow.
import { tickitz } from "./lib/tickitz"; // ── 1. Create a customer ──────────────────────────── const customer = await tickitz.customers.create({ email: "jane@example.com", firstName: "Jane", lastName: "Doe", }); // ── 2. Book tickets ───────────────────────────────── const booking = await tickitz.bookings.create({ eventId: "evt_abc123", customerId: customer.id, items: [{ tierId: "tier_ga", quantity: 2 }], }); console.log(booking.status); // "pending" console.log(booking.totalAmount); // 9998 (cents) // ── 3. Confirm after payment ──────────────────────── const confirmed = await tickitz.bookings.confirm(booking.id, { paymentIntentId: "pi_stripe_abc", // optional }); console.log(confirmed.status); // "confirmed" // Tickets are now issued automatically // ── 4. Check in at the door ───────────────────────── const scan = await tickitz.checkin.scan({ qrPayload: scannedQRString, eventId: "evt_abc123", scannedBy: "gate_staff_1", }); if (scan.success) { console.log(`Welcome, ${scan.attendeeName}!`); // "Welcome, Jane Doe!" }
Core concepts
Understanding these five concepts will help you design your integration correctly the first time.
An Event is the top-level object — it has a date, location, and capacity. Inside each event, Tiers define distinct ticket types (GA, VIP, Early Bird) with their own price, quantity, and per-order limits. Prices are always in the smallest currency unit (cents).
evt_ · tier_A Booking represents a customer's purchase intent. It moves through a lifecycle: pending → confirmed → tickets issued. Bookings are separate from payment — you collect payment yourself and call confirm() after. This keeps Tickitz payment-provider agnostic.
For high-demand events (concerts, drops), use the Queue module. Customers join a virtual waiting room; the SDK manages position polling for you. When a customer reaches the front, seats are locked for a timer window while they check out — preventing overselling entirely.
qtkn_Webhooks deliver real-time POST notifications to your endpoint when events happen — bookings confirmed, tickets scanned, fraud alerts. All payloads are HMAC-signed with SHA-256. Always verify the X-Tickitz-Signature header before processing.
Every booking gets an automatic risk score from 0–100 based on velocity, email reputation, and behavioural signals. Scores above 70 trigger a fraud.alert webhook. You decide to approve, hold, or cancel — Tickitz never blocks bookings automatically.
Tickets are issued automatically on booking confirmation. Each has a unique cryptographically signed QR payload. On event day, call checkin.scan() with the raw QR string — it verifies, records the check-in, and prevents re-entry in one atomic operation.
Common tasks
Practical guides for the most common integration scenarios. Each links to the full API reference.
Create scoped keys for each service, rotate them without downtime, and revoke compromised keys instantly. Use separate keys for test and production environments.
View guideRegister an HTTPS endpoint, subscribe to specific event types, verify HMAC signatures, and handle retries. Test delivery with webhooks.ping() before going live.
Pull event stats, revenue breakdowns, scan rates, and API usage programmatically via the Dashboard module. Build custom reports or push data to your BI tool.
View guideUse tzk_test_ keys to simulate the full booking lifecycle, generate fake QR codes, trigger webhook deliveries, and test fraud signals without affecting real data.
Invite team members, assign roles (admin, developer, read-only), and create scoped API keys per role. Pro plans support up to 5 seats; Business supports 20.
View guideEnable debug: true on the client to log every request and response. Use request IDs from error objects to trace issues. Check the status page for incidents.
Enable the waiting room for sold-out drops and concerts. The SDK's queue.poll() handles position updates with exponential backoff — no manual polling loop needed.
Tickets are auto-issued on confirmation. Retrieve the signed QR payload, render it into a QR image in your app, and use checkin.scan() in your gate scanner.
Subscribe to fraud.alert webhooks. Pull per-booking risk scores with fraud.getBookingRisk(). Resolve signals as legitimate or fraudulent to train the model.
SDK & runtimes
The SDK ships as a dual ESM/CJS package. It runs natively in any environment that supports the Fetch API.
import { Tickitz } from "@tickitz/sdk"; // Single instance — reuse across modules export const tickitz = new Tickitz({ apiKey: process.env.TICKITZ_API_KEY!, });
Configuration
Keep all Tickitz config in environment variables. Never hard-code API keys or commit them to source control.
.env* to your .gitignore. Use a secrets manager (AWS Secrets Manager, Vercel Environment Variables, Doppler) for production keys. Rotate compromised keys immediately from the dashboard.tzk_test_ for dev/staging, tzk_live_ for production onlyTICKITZ_WEBHOOK_SECRET separately — it's used to verify every incoming webhook payloaddebug: true only in development — it logs full request/response bodies which may contain PIImaxRetries: 3 in production for better resilience against transient network errorstickitz.auth.validateKey() to catch misconfiguration earlyArchitecture
Understanding the state machine behind bookings helps you build the right UI and handle edge cases gracefully.
queued state between intent and pending. Use bookings.enqueue() and queue.poll() to manage this automatically.booking.expired webhooks to release held inventory and notify the customer.Best practices
Patterns we recommend from working with hundreds of integrations.
Instantiate Tickitz once at application start. The client maintains an internal connection pool and retry state — creating a new instance per request wastes resources.
Import specific error classes like RateLimitError, NotFoundError, and BusinessError. Each carries structured data — don't catch generic Error and lose that context.
Every webhook POST includes an X-Tickitz-Signature header. Always compute the expected HMAC-SHA256 and compare before processing. Reject anything that doesn't match.
All monetary values in the API use the smallest currency unit — cents for USD, pence for GBP, paise for INR. A price of 4999 = $49.99. Format for display in your UI layer, never in the API layer.
Pending bookings expire after 30 minutes if not confirmed. Subscribe to booking.expired webhooks to release inventory, notify the customer, and update your UI in real time.
If your server crashes between collecting payment and calling confirm(), you risk double-charging. Pass the same paymentIntentId to make confirm operations idempotent and safe to retry.
Troubleshooting
Quick fixes for the most common problems developers run into.
Still stuck? Our team typically responds within a few hours.
The API Playground lets you try every endpoint interactively, with real responses — no code required.