Quickstart Core Concepts Common Tasks SDK Setup Environment Booking Flow Best Practices Troubleshooting
Updated for SDK v1.0.1

Get from zero to
live tickets in minutes

Everything you need to integrate Tickitz — step-by-step guides, real code examples, and best practices from our team.

Quickstart guide

Follow these five steps to go from a blank project to a working ticketed event with QR check-in. Takes about 10 minutes.

Your progress Step 1 of 5
1
Step 01 — Account

Create your account & get an API key

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.

  • Visit tickitz.io and click "Get started free"
  • Enter your email and verify it — takes 30 seconds
  • Go to Settings → API Keys → Create New Key
  • Name it "Development" and copy the key — it starts with tzk_test_
  • Store it in a .env file — never commit it to Git
Keep test and live keys separate. Use tzk_test_ keys in development and tzk_live_ keys only in production. Live keys process real bookings.
2
Step 02 — Install

Install the SDK

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
Node.js 18+ required. The SDK uses the native fetch API. No polyfills needed. For older Node versions, pass a fetch option to the constructor.
3
Step 03 — Initialize

Initialize the client

Create a single Tickitz instance and reuse it across your application. The client handles retries, rate limit backoff, and request signing automatically.

lib/tickitz.ts
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
});
Tip: In Next.js, export this from a singleton module so it's shared across route handlers. In Express, attach it to app.locals.
4
Step 04 — Create

Create and publish your first event

Events start in draft status. Once you've configured tiers and capacity, publish to make them live and accepting bookings.

create-event.ts
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"
5
Step 05 — Book & Check in

Accept a booking and check in attendees

The full lifecycle: create a customer, book tickets, confirm after payment, then scan QR codes at the door. All in one flow.

booking-flow.ts
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!"
}
You're live! That's the full Tickitz flow. Explore the API Playground to try any endpoint interactively, or read the Core Concepts below to go deeper.

How Tickitz works

Understanding these five concepts will help you design your integration correctly the first time.

Events & Tiers

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_

Bookings

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.

bkg_

Queue / Waiting Room

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

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.

wh_

Fraud Detection

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.

frd_

Tickets & QR

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.

tkt_

Everything you'll need to build

Practical guides for the most common integration scenarios. Each links to the full API reference.

Manage API Keys

Create scoped keys for each service, rotate them without downtime, and revoke compromised keys instantly. Use separate keys for test and production environments.

View guide

Set Up Webhooks

Register an HTTPS endpoint, subscribe to specific event types, verify HMAC signatures, and handle retries. Test delivery with webhooks.ping() before going live.

View guide

View Analytics

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 guide

Test in Sandbox

Use tzk_test_ keys to simulate the full booking lifecycle, generate fake QR codes, trigger webhook deliveries, and test fraud signals without affecting real data.

Open Playground

Manage Team Access

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 guide

Debug Requests

Enable 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.

View guide

Queue High-Demand Events

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.

View guide

Issue & Scan Tickets

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.

View guide

Handle Fraud Signals

Subscribe to fraud.alert webhooks. Pull per-booking risk scores with fraud.getBookingRisk(). Resolve signals as legitimate or fraudulent to train the model.

View guide

Works everywhere
you deploy

The SDK ships as a dual ESM/CJS package. It runs natively in any environment that supports the Fetch API.

server.ts — Node.js 18+
import { Tickitz } from "@tickitz/sdk";

// Single instance — reuse across modules
export const tickitz = new Tickitz({
  apiKey: process.env.TICKITZ_API_KEY!,
});

Environment setup

Keep all Tickitz config in environment variables. Never hard-code API keys or commit them to source control.

# .env.local — development
TICKITZ_API_KEY=tzk_test_abc123def456ghi789
TICKITZ_WEBHOOK_SECRET=whsec_xyz789abc123
TICKITZ_BASE_URL=https://api.tickitz.com # optional override

# .env.production — production (use secrets manager in CI)
TICKITZ_API_KEY=tzk_live_abc123def456ghi789
TICKITZ_WEBHOOK_SECRET=whsec_prod_xyz789abc123
Always add .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.

Environment checklist

Separate keys per environmenttzk_test_ for dev/staging, tzk_live_ for production only
Store TICKITZ_WEBHOOK_SECRET separately — it's used to verify every incoming webhook payload
Enable debug: true only in development — it logs full request/response bodies which may contain PII
Set maxRetries: 3 in production for better resilience against transient network errors
Validate your API key on startup with tickitz.auth.validateKey() to catch misconfiguration early

The booking lifecycle

Understanding the state machine behind bookings helps you build the right UI and handle edge cases gracefully.

Customer joins
intent
pending
bkg_ created
payment
your system
confirmed
confirm()
tkt_ issued
auto
scanned
check-in
High demand? Insert a queued state between intent and pending. Use bookings.enqueue() and queue.poll() to manage this automatically.
Pending bookings expire after 30 minutes by default. Subscribe to booking.expired webhooks to release held inventory and notify the customer.

Build it right
the first time

Patterns we recommend from working with hundreds of integrations.

1

Use a singleton client

Instantiate Tickitz once at application start. The client maintains an internal connection pool and retry state — creating a new instance per request wastes resources.

Export from a shared module
new Tickitz() inside each handler
2

Always catch typed errors

Import specific error classes like RateLimitError, NotFoundError, and BusinessError. Each carries structured data — don't catch generic Error and lose that context.

catch (err instanceof RateLimitError)
catch (e) { console.log(e.message) }
3

Verify webhook signatures

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.

Verify sig before processing payload
Trust the payload without verification
4

Prices are always in cents

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.

price: 4999 (cents)
price: 49.99 (floats cause bugs)
5

Handle booking expiry

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.

Listen to booking.expired webhook
Poll booking status every few seconds
6

Use idempotency for confirms

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.

Pass paymentIntentId on confirm()
Confirm without idempotency key

Common errors
& how to fix them

Quick fixes for the most common problems developers run into.

401 UnauthorizedError
Invalid or missing API key
Your TICKITZ_API_KEY environment variable is missing, expired, or malformed. Check it starts with tzk_test_ (dev) or tzk_live_ (prod). Verify it hasn't been revoked in the dashboard under Settings → API Keys.
422 BusinessError: event_sold_out
Booking attempt exceeds capacity
The tier you're booking into has no remaining inventory. Check event.tiers[n].sold vs event.tiers[n].quantity before attempting a booking. For high-demand events, use the Queue module to avoid this entirely.
429 RateLimitError
Too many requests
You've exceeded your plan's rate limit. The error includes a retryAfter property in seconds — wait that long before retrying. The SDK retries automatically up to maxRetries times. For sustained high traffic, upgrade your plan or add the rate limit add-on.
NetworkError: fetch failed
Cannot reach the API
Usually a DNS resolution failure, firewall rule, or Node.js version below 18 (no native fetch). Check your server has outbound HTTPS access to api.tickitz.com. Verify with curl https://api.tickitz.com/health. On Node < 18, pass a fetch polyfill.
Webhook: 401 Invalid signature
Signature mismatch on incoming webhook
The TICKITZ_WEBHOOK_SECRET you're using doesn't match the one shown in the dashboard for this webhook endpoint. Make sure you're using req.rawBody (not the parsed JSON) when computing the HMAC — body parsers modify the payload and break the signature.

Still stuck? Our team typically responds within a few hours.

Contact support Open an issue

Everything you need
is right here.

The API Playground lets you try every endpoint interactively, with real responses — no code required.