TypeScript Types

The @qariyb/js package includes full TypeScript definitions. Import types directly from the package.

import type { QariybEvent, Order, Cart } from '@qariyb/js';

API Response Types

QariybEvent

Event data returned from the API.

interface QariybEvent {
  /** ULID (26-char alphanumeric) */
  id: string;
  title: string;
  slug: string;
  /** Summary (max 200 chars) or truncated description */
  summary: string | null;
  /** Full HTML description */
  description: string | null;

  pricing_model: PricingModel;
  /** 3-letter ISO 4217 code, uppercase. Never null — free events fall back. */
  currency: string;

  /** YYYY-MM-DD */
  start_date: string | null;
  /** HH:MM:SS */
  start_time: string | null;
  end_date: string | null;
  end_time: string | null;
  /** IANA identifier, e.g. 'Europe/London'. Defaults to 'UTC'. */
  timezone: string;
  /** Full ISO 8601 datetime in UTC */
  start_datetime_utc: string | null;
  end_datetime_utc: string | null;

  is_online: boolean;
  virtual_platform: string | null;
  address: EventAddress | null;

  has_tickets: boolean;
  requires_registration: boolean;
  requires_approval: boolean;
  registration_open: boolean;
  is_sold_out: boolean;

  category: EventCategory | null;
  organization: EventOrganization | null;
  cover_image: EventCoverImage;
  /** Only ticket types that are active and currently available */
  ticket_types: TicketType[];
  features: EventFeature[];

  /** Full URL to the event's public discovery page */
  public_url: string;
}

type PricingModel = 'free' | 'paid' | 'external';

EventAddress

interface EventAddress {
  venue_name: string | null;
  city: string | null;
  state: string | null;
  country: string | null;
  /** Venue, city, state, country joined with ', ' — empty parts dropped */
  display_address: string;
}

EventCategory

interface EventCategory {
  name: string;
  slug: string;
}

EventOrganization

interface EventOrganization {
  name: string;
  slug: string;
  /** Logo URL, or null */
  logo: string | null;
  is_verified: boolean;
}

EventCoverImage

interface EventCoverImage {
  url: string;
  alt_text: string;
}

TicketType

interface TicketType {
  /** ULID */
  id: string;
  name: string;
  description: string | null;
  /** Price in minor units (e.g. cents/pence) */
  price_cents: number;
  currency: string;
  /**
   * Units a buyer can actually purchase right now. Already excludes stock held
   * in other shoppers' live carts, so it can be lower than physical remaining
   * inventory.
   *
   * Null when the ticket type is uncapped: that means "no limit", not "none
   * left". Do not render null as a count and do not read it as sold out —
   * only max_per_order bounds an uncapped type.
   */
  quantity_available: number | null;
  /** Defaults to 10 when the organizer sets no cap */
  max_per_order: number;
  /** Defaults to 1 */
  min_per_order: number;
  /** True when price_cents is 0 */
  is_free: boolean;
}

EventFeature

interface EventFeature {
  name: string;
  slug: string;
  category: string | null;
}

EventAvailabilityResponse

Response from GET /v1/public/events/{ulid}/availability. Only available and reason are guaranteed. The rest are populated only on success paths and omitted when reason is 'event_not_found' or 'event_not_available'.

interface EventAvailabilityResponse {
  available: boolean;
  reason: 'event_not_found' | 'event_not_available' | 'sold_out' | 'registration_closed' | null;
  event_id?: string;
  registration_open?: boolean;
  has_tickets?: boolean;
  is_sold_out?: boolean;
  total_tickets_available?: number;
}

OrganizationEventsResponse

Response from GET /v1/public/organizations/{ulid}/events. Flat array of events using the same shape as QariybEvent.

type OrganizationEventsResponse = QariybEvent[];

Checkout Types

CheckoutInitResponse

Response from the checkout initialize endpoint.

interface CheckoutInitResponse {
  cart_id: string;
  /** null for free events, which have no payment to make */
  stripe: StripeCredentials | null;
  amount: number;
  /** 3-letter ISO 4217 currency code, uppercase (e.g. 'USD'). */
  currency: string;
  is_free_event: boolean;
  custom_questions: CustomQuestion[];
  expires_at: string;
  /** Phone field display mode resolved from event registration settings. */
  phone_field_type: 'required' | 'optional' | 'off';
}

StripeCredentials

interface StripeCredentials {
  /** Stripe publishable key (pk_live_…) */
  publishable_key: string;
  /** PaymentIntent client secret (pi_…_secret_…) */
  client_secret: string;
  /** Connected account the PaymentIntent lives on, or null */
  connected_account_id: string | null;
}

CheckoutConfirmResponse

Response from the checkout confirm endpoint.

interface CheckoutConfirmResponse {
  order: Order;
  tickets: OrderTicket[];
  requires_approval: boolean;
}

Order

interface Order {
  /** ULID — the stable key, not the reference a buyer quotes */
  id: string;
  /** Human-readable order number, e.g. 'ORD2026HTP9PWGC'. Show this one. */
  number: string;
  status: OrderStatus;
  /** Ticket total before any discount, in minor units */
  subtotal: number;
  /** Amount taken off by a discount code, in minor units; 0 when none */
  discount_amount: number;
  total: number;
  /** 3-letter ISO 4217 currency code, uppercase (e.g. 'USD'). */
  currency: string;
  billing_name: string;
  billing_email: string;
  requires_approval: boolean;
  /** ISO 8601 datetime the order was placed */
  created_at: string;
}

type OrderStatus =
  | 'pending'
  | 'completed'
  | 'cancelled'
  | 'refunded'
  | 'failed'
  | 'refund_pending';

OrderTicket

interface OrderTicket {
  id: string;
  /** Human-readable ticket number, e.g. 'TKZHHQ6RD8E4VQ' */
  number: string;
  ticket_type: string;
  status: TicketStatus;
  attendee_name: string | null;
}

type TicketStatus =
  | 'purchased'
  | 'used'
  | 'cancelled'
  | 'refunded'
  | 'transferred'
  | 'pending_approval';

CustomQuestion

interface CustomQuestion {
  id: string;
  question: string;
  type: CustomQuestionType;
  required: boolean;
  /** Options for select/checkbox/radio; null for text */
  options: string[] | null;
  display_order: number;
}

type CustomQuestionType = 'text' | 'select' | 'checkbox' | 'radio';

ApplyDiscountRequest

Request body for the discount endpoint.

interface ApplyDiscountRequest {
  /** Cart ULID from checkout initialize */
  cart_id: string;
  /** The code the buyer typed */
  code: string;
  /** Stripe PaymentIntent id — see paymentIntentIdFromSecret() */
  payment_intent_id: string;
}

DiscountApplication

A discount that has been applied to the checkout's PaymentIntent. The server has already repriced the intent when this resolves, so new_total is what the card will actually be charged.

interface DiscountApplication {
  /** Canonical code as stored — may differ in case from what was typed */
  code: string;
  discount_type: DiscountType;
  /** Readable form of discount_type: 'percentage' or 'fixed_amount' */
  discount_type_name: string;
  /** Whole percentage points when type is 2, minor units when type is 1 */
  discount_value: number;
  /** Display-ready value, e.g. '20%' or '£5.00' */
  formatted_value: string;
  /** Amount taken off, in minor units */
  discount_amount: number;
  /** New charge amount, in minor units */
  new_total: number;
  currency: string;
}

/** 1 = fixed amount, 2 = percentage */
type DiscountType = 1 | 2;

export const DISCOUNT_TYPE_FIXED_AMOUNT = 1;
export const DISCOUNT_TYPE_PERCENTAGE = 2;

EventTicketsResponse

Response from GET /v1/public/events/{ulid}/tickets.

interface EventTicketsResponse {
  event_id: string;
  currency: string;
  ticket_types: TicketType[];
  registration_open: boolean;
  is_sold_out: boolean;
}

OrganizationEventsPage

A page of organization events together with the window it came from. Returned by QariybApiClient.getOrganizationEventsPage().

interface OrganizationEventsPage {
  events: QariybEvent[];
  /** Total matching events, or null when the header is unreadable */
  total: number | null;
  /** Echoed window, or null when the headers are unreadable */
  limit: number | null;
  offset: number | null;
}

ValidationErrors

/** Field name → list of error messages */
type ValidationErrors = Record<string, string[]>;

RSVP Types

RsvpRegistration

Response body from the RSVP endpoint. This shape is documented for direct API callers — @qariyb/js does not export it as a type, because the SDK's components do not drive RSVP.

interface RsvpRegistration {
  registration: {
    id: string;
    status: 'confirmed' | 'pending_approval';
    name: string;
    email: string;
    requires_approval: boolean;
  };
}

Cart Types

Cart

interface Cart {
  items: CartItem[];
  totalCents: number;
  totalQuantity: number;
  currency: string;
}

CartItem

interface CartItem {
  ticketTypeId: string;
  ticketTypeName: string;
  quantity: number;
  priceCents: number;
  currency: string;
}

Configuration Types

QariybConfig

interface QariybConfig {
  // API Configuration
  publishableKey?: string;
  apiBaseUrl?: string;
  debug?: boolean;

  // Layer 1: Theme Preset
  theme?: ThemePreset;

  // Layer 2: Variable Overrides
  variables?: ThemeVariables | ThemeVariableOverrides;

  // Layer 3: Component Rules
  rules?: ComponentRules;

  // Feature Flags
  features?: FeatureFlags;

  // Internationalization
  locale?: string;
  labels?: Partial<Labels>;
}

ThemePreset

type ThemePreset = 'light' | 'dark' | 'flat' | 'minimal';

ThemeVariableOverrides

interface ThemeVariableOverrides {
  colorPrimary?: string;
  colorPrimaryText?: string;
  colorBackground?: string;
  colorBackgroundSecondary?: string;
  colorText?: string;
  colorTextSecondary?: string;
  colorSuccess?: string;
  colorError?: string;
  colorWarning?: string;
  colorBorder?: string;
  colorIcon?: string;
  fontFamily?: string;
  borderRadius?: string;
  buttonHeight?: string;
  inputHeight?: string;
  spacingUnit?: string;
}

FeatureFlags

interface FeatureFlags {
  showBranding?: boolean;       // Default: true
  showPaymentIcons?: boolean;   // Default: true
  showSecurityBadge?: boolean;  // Default: true
  skeletonLoading?: boolean;    // Default: true
}

ComponentRules

interface ComponentRules {
  '.Container'?: CSSProperties;
  '.Section'?: CSSProperties;
  '.Button'?: CSSProperties;
  '.Button--primary'?: CSSProperties;
  '.Button--secondary'?: CSSProperties;
  '.Input'?: CSSProperties;
  '.Label'?: CSSProperties;
  '.TicketRow'?: CSSProperties;
  '.TicketRow--selected'?: CSSProperties;
  '.QuantityControl'?: CSSProperties;
  '.OrderSummary'?: CSSProperties;
  '.Modal'?: CSSProperties;
  '.EventCard'?: CSSProperties;
  // ... and more
  [key: string]: CSSProperties | undefined;
}

Component State Types

CheckoutStep

type CheckoutStep =
  | 'loading'
  | 'tickets'
  | 'details'
  | 'payment'
  | 'processing'
  | 'success'
  | 'error';

CheckoutState

interface CheckoutState {
  step: CheckoutStep;
  event: QariybEvent | null;
  cart: Cart;
  cartId: string | null;
  clientSecret: string | null;
  publishableKey: string | null;
  /** Connected account the PaymentIntent lives on (direct charges), or null */
  connectedAccountId: string | null;
  customQuestions: CustomQuestion[];
  order: Order | null;
  tickets: OrderTicket[];
  error: string | null;
  requiresApproval: boolean;
  /** Field-level validation errors from the server */
  fieldErrors: ValidationErrors;
  /** Whether a form submission is in progress */
  isSubmitting: boolean;
  /** Typed contact details, kept across re-renders so the form is not cleared */
  contactDetails: { name: string; email: string; phone: string };
  /** Phone field display mode from checkout initialize */
  phoneFieldType: 'required' | 'optional' | 'off';

  /** Discount code currently entered by the user */
  discountCode: string;
  /**
   * Discount the server has applied to the PaymentIntent, or null. Non-null
   * means the card will be charged `appliedDiscount.new_total` rather than
   * `cart.totalCents`.
   */
  appliedDiscount: DiscountApplication | null;
  /** Message from the last rejected discount attempt */
  discountError: string | null;
  /** Whether a discount request is in flight */
  isApplyingDiscount: boolean;
}

Event Detail Types

QariybEventDetail

Base detail interface for all events.

interface QariybEventDetail<T = unknown> {
  timestamp: number;      // Unix timestamp
  component: string;      // 'checkout', 'tickets', 'button', etc.
  action: string;         // 'success', 'error', 'ready', etc.
  data: T;                // Event-specific payload
}

QariybCustomEvent

Type for CustomEvent with proper detail typing.

type QariybCustomEvent<T = unknown> = CustomEvent<QariybEventDetail<T>>;

Checkout Event Details

interface CheckoutReadyDetail {
  eventId: string;
}

interface CheckoutEventLoadedDetail {
  event: QariybEvent;
}

interface CheckoutEventErrorDetail {
  error: string;
  eventId: string;
}

interface CheckoutStepChangedDetail {
  from: CheckoutStep;
  to: CheckoutStep;
  eventId: string;
}

interface CheckoutCartUpdatedDetail {
  cart: Cart;
  action: 'add' | 'remove' | 'clear';
  ticketId?: string;
  ticketName?: string;
}

interface CheckoutDetailsSubmittedDetail {
  email: string;
  name: string;
  phone?: string;
}

interface CheckoutPaymentStartedDetail {
  cartId: string;
  amount: number;
  currency: string;
}

interface CheckoutPaymentProcessingDetail {
  paymentIntentId?: string;
}

interface CheckoutSuccessDetail {
  order: Order;
  tickets: OrderTicket[];
  requiresApproval: boolean;
}

interface CheckoutDiscountAppliedDetail {
  discount: DiscountApplication;
  /** Total before the discount, in minor units */
  previousTotal: number;
}

interface CheckoutDiscountFailedDetail {
  code: string;
  /** Human-readable reason from the server */
  error: string;
}

interface CheckoutErrorDetail {
  error: string;
  code?: string;
  step?: CheckoutStep;
}

interface CheckoutValidationErrorDetail {
  errors: ValidationErrors;
  step: CheckoutStep;
}

Tickets Event Details

interface TicketsReadyDetail {
  eventId: string;
}

interface TicketsLoadedDetail {
  tickets: TicketType[];
  event: QariybEvent;
}

interface TicketsQuantityChangedDetail {
  ticketId: string;
  ticketName: string;
  quantity: number;
  previousQuantity: number;
  price: number;
  currency: string;
}

interface TicketsSelectedDetail {
  cart: Cart;
  eventId: string;
}

interface TicketsErrorDetail {
  error: string;
  eventId: string;
}

Button Event Details

interface ButtonReadyDetail {
  eventId: string;
}

interface ButtonModalOpenedDetail {
  eventId: string;
}

interface ButtonModalClosedDetail {
  eventId: string;
  reason: 'success' | 'cancel' | 'escape' | 'overlay';
}

Card Event Details

interface CardReadyDetail {
  eventId: string;
}

interface CardLoadedDetail {
  event: QariybEvent;
}

interface CardClickedDetail {
  event: QariybEvent;
  action: 'view' | 'tickets';
}

interface CardErrorDetail {
  error: string;
  eventId: string;
}

List Event Details

interface ListReadyDetail {
  organizationId: string;
}

interface ListLoadedDetail {
  events: QariybEvent[];
  total: number;
  hasMore: boolean;
}

interface ListErrorDetail {
  error: string;
  organizationId: string;
}

Importing Types

// API types
import type {
  QariybEvent,
  TicketType,
  EventAddress,
  EventCategory,
  EventOrganization,
  EventFeature,
  Order,
  OrderTicket,
  CustomQuestion,
} from '@qariyb/js';

// RSVP types
import type { RsvpRegistration } from '@qariyb/js';

// Cart types
import type { Cart, CartItem } from '@qariyb/js';

// Config types
import type {
  QariybConfig,
  ThemePreset,
  ThemeVariableOverrides,
  FeatureFlags,
  ComponentRules,
} from '@qariyb/js';

// State types
import type { CheckoutStep, CheckoutState } from '@qariyb/js';

// Event types
import type {
  QariybEventDetail,
  QariybCustomEvent,
  CheckoutSuccessDetail,
  CheckoutErrorDetail,
  TicketsSelectedDetail,
  // ... etc.
} from '@qariyb/js';

Was this page helpful?