npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tickitz/sdk

v1.0.1

Published

The official TypeScript SDK for the Tickitz ticketing infrastructure platform

Downloads

283

Readme

@tickitz/sdk

The official TypeScript SDK for the Tickitz ticketing infrastructure platform.

npm version CI TypeScript License: MIT


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/sdk

Quick 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
       ↘ refunded

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