@tickitz/sdk
v1.0.1
Published
The official TypeScript SDK for the Tickitz ticketing infrastructure platform
Downloads
283
Maintainers
Readme
@tickitz/sdk
The official TypeScript SDK for the Tickitz ticketing infrastructure platform.
Features
- Fully typed — every method has complete TypeScript types for inputs and outputs
- Stripe-style API — clean, intuitive, modular interface
- Fetch-based — works in Node.js 18+, browsers, and edge runtimes
- Smart retries — automatic retry with exponential backoff on transient errors
- Typed errors — specific error classes for every failure mode
- Tree-shakeable — import only what you need
- ESM + CJS — works everywhere
Installation
npm install @tickitz/sdk
# or
pnpm add @tickitz/sdk
# or
yarn add @tickitz/sdkQuick Start
import { Tickitz } from "@tickitz/sdk";
const tickitz = new Tickitz({
apiKey: "tzk_live_...", // Get yours at https://tickitz-cyan.vercel.app
});
// Create an event
const event = await tickitz.events.create({
title: "Summer Music Festival",
description: "An incredible outdoor experience.",
startsAt: "2025-07-15T18:00:00Z",
endsAt: "2025-07-15T23:00:00Z",
location: {
venue: "Riverside Amphitheater",
address: "123 River Rd",
city: "Austin",
state: "TX",
country: "US",
},
tiers: [
{ name: "General Admission", price: 4999, currency: "USD", quantity: 500 },
{ name: "VIP", price: 14999, currency: "USD", quantity: 50 },
],
});
// Publish it
await tickitz.events.publish(event.id);
// Create a customer
const customer = await tickitz.customers.create({
email: "[email protected]",
firstName: "Jane",
lastName: "Doe",
});
// Book tickets
const booking = await tickitz.bookings.create({
eventId: event.id,
customerId: customer.id,
items: [{ tierId: event.tiers[0].id, quantity: 2 }],
});
// Confirm after payment
await tickitz.bookings.confirm(booking.id, { paymentIntentId: "pi_..." });Configuration
const tickitz = new Tickitz({
apiKey: "tzk_live_...", // Required
baseURL: "https://api.tickitz.com", // Optional — default
timeout: 30_000, // Optional — ms, default 30s
maxRetries: 2, // Optional — default 2
headers: { // Optional — extra headers on every request
"X-App-Version": "2.1.0",
},
debug: false, // Optional — logs requests/responses
});Local Development
import { Tickitz, LOCAL_BASE_URL } from "@tickitz/sdk";
const tickitz = new Tickitz({
apiKey: "tzk_test_...",
baseURL: LOCAL_BASE_URL, // "http://localhost:8787"
});Modules
tickitz.auth
// Validate your API key
const isValid = await tickitz.auth.validateKey();
// Get API key details
const keyInfo = await tickitz.auth.getKeyInfo();
console.log(keyInfo.scopes, keyInfo.expiresAt);
// Get full auth status including org info
const status = await tickitz.auth.getStatus();
console.log(status.organization.plan); // "pro"tickitz.events
// Create
const event = await tickitz.events.create({ ... });
// Publish
await tickitz.events.publish(event.id);
// Get
const event = await tickitz.events.get("evt_123");
// List with filters
const { data, meta } = await tickitz.events.list({
status: "published",
tags: ["music"],
sortBy: "startsAt",
sortOrder: "asc",
page: 1,
limit: 20,
});
// Update
await tickitz.events.update("evt_123", { title: "New Title" });
// Delete (draft/cancelled only)
await tickitz.events.delete("evt_123");tickitz.customers
const customer = await tickitz.customers.create({
email: "[email protected]",
firstName: "Jane",
lastName: "Doe",
});
const found = await tickitz.customers.get("cus_123");
const { data } = await tickitz.customers.list({ search: "jane", limit: 10 });
await tickitz.customers.update("cus_123", { phone: "+15551234567" });
await tickitz.customers.delete("cus_123");tickitz.bookings
// Direct booking (bypasses queue)
const booking = await tickitz.bookings.create({
eventId: "evt_123",
customerId: "cus_456",
items: [{ tierId: "tier_789", quantity: 2 }],
});
// Enqueue for high-demand events
const queued = await tickitz.bookings.enqueue({ ... });
// Confirm after payment
await tickitz.bookings.confirm(booking.id, { paymentIntentId: "pi_..." });
// Cancel
await tickitz.bookings.cancel(booking.id);
// Get status
const status = await tickitz.bookings.getStatus(booking.id);
// "pending" | "queued" | "confirmed" | "cancelled" | "refunded" | "expired" | "failed"
// List
const { data } = await tickitz.bookings.list({ eventId: "evt_123", status: "confirmed" });Booking lifecycle:
pending → queued → confirmed → (tickets issued)
↘ cancelled
↘ expired
↘ failed
↘ refundedtickitz.queue
// Join the queue
const entry = await tickitz.queue.join({
eventId: "evt_123",
customerId: "cus_456",
items: [{ tierId: "tier_789", quantity: 2 }],
});
console.log(`Position: #${entry.position}, ETA: ${entry.estimatedWaitSeconds}s`);
// Poll until ready (handles polling loop for you)
const final = await tickitz.queue.poll(entry.token, {
intervalMs: 3000,
maxPolls: 100,
onUpdate: (pos) => console.log(`Still #${pos.position}...`),
});
if (final.status === "ready") {
const { checkoutUrl } = await tickitz.queue.startCheckout(entry.token);
// Redirect customer to checkoutUrl
}
// Check seat lock
const lock = await tickitz.queue.getSeatLock(entry.token);
// Leave voluntarily
await tickitz.queue.leave(entry.token);tickitz.tickets
// Get a ticket
const ticket = await tickitz.tickets.get("tkt_123");
// Get with QR code
const withQR = await tickitz.tickets.getWithQR("tkt_123");
console.log(withQR.qrImageUrl); // Display to customer
// List tickets
const { data } = await tickitz.tickets.list({ eventId: "evt_123", status: "active" });
// Validate without checking in
const result = await tickitz.tickets.validate("tkt_123");
if (!result.valid) console.log(result.reason);
// Mark as used
await tickitz.tickets.markAsUsed("tkt_123");tickitz.checkin
// Scan QR and check in (primary scanner method)
const result = await tickitz.checkin.scan({
qrPayload: scannedString,
eventId: "evt_123",
scannedBy: "staff_gate_1",
});
if (result.alreadyCheckedIn) {
// Duplicate scan — show warning
} else if (result.success) {
console.log(`Welcome, ${result.attendeeName}!`);
}
// Verify QR without checking in
const verify = await tickitz.checkin.verifyQR(scannedString);
// Check in by ticket ID
await tickitz.checkin.checkIn("tkt_123");
// Generate QR payload for a ticket
const payload = await tickitz.checkin.generateQRPayload("tkt_123");tickitz.webhooks
// Create
const webhook = await tickitz.webhooks.create({
url: "https://myapp.com/webhooks/tickitz",
events: ["booking.confirmed", "ticket.used", "fraud.alert"],
});
// Store webhook.signingSecret to verify incoming payloads
// Test connectivity
const ping = await tickitz.webhooks.ping(webhook.id);
console.log(`${ping.responseTime}ms`);
// List, update, delete
const { data } = await tickitz.webhooks.list({ isActive: true });
await tickitz.webhooks.update(webhook.id, { isActive: false });
await tickitz.webhooks.delete(webhook.id);
// Supported event types
const types = await tickitz.webhooks.getSupportedEvents();Verifying webhook signatures (Hono):
import { createHmac } from "crypto";
app.post("/webhooks/tickitz", async (c) => {
const sig = c.req.header("X-Tickitz-Signature");
const ts = c.req.header("X-Tickitz-Timestamp");
const raw = await c.req.text();
const expected = "sha256=" + createHmac("sha256", WEBHOOK_SECRET)
.update(`${ts}.${raw}`)
.digest("hex");
if (sig !== expected) return c.json({ error: "Invalid signature" }, 401);
const event = JSON.parse(raw);
// Handle event.type ...
return c.json({ received: true });
});tickitz.fraud
// List fraud signals
const { data } = await tickitz.fraud.listSignals({ riskLevel: "high" });
// Get risk for a specific booking
const risk = await tickitz.fraud.getBookingRisk("bkg_123");
if (risk.riskLevel === "critical") {
// Flag for manual review
}
// Resolve a signal
await tickitz.fraud.resolveSignal("frd_123", {
resolution: "legitimate",
notes: "Verified with customer",
});
// Organization risk status
const status = await tickitz.fraud.getRiskStatus();tickitz.dashboard
// Developer stats
const stats = await tickitz.dashboard.getDeveloperStats({ period: "30d" });
// Event-specific stats
const eventStats = await tickitz.dashboard.getEventStats("evt_123");
console.log(`${eventStats.capacityUsed}/${eventStats.capacityTotal} capacity used`);
// Booking stats
const bookingStats = await tickitz.dashboard.getBookingStats({ period: "7d" });
// Ticket scan stats
const scanStats = await tickitz.dashboard.getTicketScanStats("evt_123");
console.log(`Scan rate: ${(scanStats.scanRate * 100).toFixed(1)}%`);
// Webhook logs
const { data: logs } = await tickitz.dashboard.getWebhookLogs({ limit: 50 });
// Recent activity
const { data: activity } = await tickitz.dashboard.getRecentActivity({ limit: 20 });
// API usage
const usage = await tickitz.dashboard.getAPIUsage();
console.log(`${usage.totalRequests} requests this period`);Error Handling
The SDK throws typed errors for every failure mode. Always catch TickitzError as the base class.
import {
TickitzError,
ValidationError,
UnauthorizedError,
NotFoundError,
ConflictError,
RateLimitError,
NetworkError,
APIError,
BusinessError,
} from "@tickitz/sdk";
try {
await tickitz.bookings.create({ ... });
} catch (err) {
if (err instanceof ValidationError) {
// 400 — bad request params
console.error("Validation failed:", err.details);
} else if (err instanceof UnauthorizedError) {
// 401 — invalid or expired API key
console.error("Check your API key");
} else if (err instanceof NotFoundError) {
// 404 — resource doesn't exist
console.error("Not found:", err.code);
} else if (err instanceof ConflictError) {
// 409 — duplicate resource
console.error("Conflict:", err.message);
} else if (err instanceof BusinessError) {
// 422 — business rule violation (e.g., event sold out)
console.error("Business error:", err.message);
} else if (err instanceof RateLimitError) {
// 429 — too many requests
console.error(`Rate limited. Retry in ${err.retryAfter}s`);
await sleep(err.retryAfter * 1000);
} else if (err instanceof NetworkError) {
// Network timeout or DNS failure
console.error("Network error:", err.cause);
} else if (err instanceof APIError) {
// 5xx — server error
console.error("Server error:", err.status, err.requestId);
} else if (err instanceof TickitzError) {
// Catch-all for any Tickitz error
console.error(err.code, err.status, err.requestId);
}
}Every error includes:
| Property | Type | Description |
|---|---|---|
| code | string | Machine-readable error code |
| message | string | Human-readable description |
| status | number | HTTP status code |
| requestId | string? | Unique request ID for support |
| details | object? | Additional context |
Rate Limiting
The SDK automatically retries on 429 Too Many Requests using the Retry-After header. You can also inspect rate limit info from errors:
try {
await tickitz.events.list();
} catch (err) {
if (err instanceof RateLimitError) {
console.log(`Retry after ${err.retryAfter} seconds`);
}
}Pagination
All list methods return a PaginatedResponse<T>:
const { data, meta } = await tickitz.events.list({ page: 1, limit: 20 });
console.log(meta.total); // Total records
console.log(meta.hasNextPage); // Whether more pages exist
console.log(meta.nextCursor); // Cursor for cursor-based pagination
// Fetch next page
if (meta.hasNextPage) {
const next = await tickitz.events.list({ page: 2, limit: 20 });
}Environment Setup
Node.js
Requires Node.js 18+ (uses native fetch).
node --version # v18.0.0+Environment Variables
# .env
TICKITZ_API_KEY=tzk_live_...const tickitz = new Tickitz({
apiKey: process.env.TICKITZ_API_KEY!,
});Vercel / Edge Runtime
The SDK uses the standard fetch API and is fully compatible with Vercel Edge Functions and Cloudflare Workers.
// api/events/route.ts (Next.js App Router)
import { Tickitz } from "@tickitz/sdk";
export const runtime = "edge";
export async function GET() {
const tickitz = new Tickitz({ apiKey: process.env.TICKITZ_API_KEY! });
const { data } = await tickitz.events.list({ status: "published" });
return Response.json(data);
}Hono Backend
import { Hono } from "hono";
import { Tickitz } from "@tickitz/sdk";
const app = new Hono();
const tickitz = new Tickitz({ apiKey: process.env.TICKITZ_API_KEY! });
app.get("/events", async (c) => {
const events = await tickitz.events.list({ status: "published" });
return c.json(events);
});API Reference
Full API documentation: https://github.com/Vsp111R/TICKITZ#readme
Contributing
See CONTRIBUTING.md for development setup and contribution guidelines.
License
MIT © Tickitz
