← Back to guidesGUIDE · TYPESCRIPT

Call ticket APIs from TypeScript

TypeScript14 minIntermediate

The Alga PSA REST API is easy to call from TypeScript with a small fetch wrapper. This guide shows a practical pattern for tickets: one request helper, typed payloads, and explicit error handling.

Start with a tiny request helper

alga.ts
const API_BASE = 'https://algapsa.com';
const API_KEY = process.env.ALGA_API_KEY!;

type AlgaError = {
  error?: {
    code?: string;
    message?: string;
    details?: unknown;
  };
};

async function algaFetch<T>(path: string, init?: RequestInit): Promise<T> {
  const response = await fetch(API_BASE + path, {
    ...init,
    headers: {
      'X-API-Key': API_KEY,
      ...(init?.body ? { 'Content-Type': 'application/json' } : {}),
      ...(init?.headers ?? {}),
    },
  });

  const payload = (await response.json()) as T & AlgaError;
  if (!response.ok) {
    throw new Error(payload.error?.message ?? 'Request failed');
  }
  return payload;
}

Add ticket-specific types

tickets.ts
export type CreateTicketInput = {
  title: string;
  board_id: string;
  client_id: string;
  status_id: string;
  priority_id: string;
  assigned_to?: string;
  category_id?: string;
  tags?: string[];
};

export type TicketRecord = {
  ticket_id: string;
  ticket_number: string;
  title: string;
  board_id: string;
  client_id: string;
  status_id: string;
  priority_id: string;
};

List tickets

tickets.ts
export async function listTickets(page = 1, limit = 25) {
  return algaFetch<{
    data: TicketRecord[];
    pagination: {
      page: number;
      limit: number;
      total: number;
      totalPages: number;
      hasNext: boolean;
      hasPrev: boolean;
    };
  }>('/api/v1/tickets?page=' + page + '&limit=' + limit);
}

Create and update a ticket

tickets.ts
export async function createTicket(input: CreateTicketInput) {
  return algaFetch<{ data: TicketRecord }>('/api/v1/tickets', {
    method: 'POST',
    body: JSON.stringify(input),
  });
}

export async function updateTicket(ticketId: string, updates: Partial<CreateTicketInput>) {
  return algaFetch<{ data: TicketRecord }>('/api/v1/tickets/' + ticketId, {
    method: 'PUT',
    body: JSON.stringify(updates),
  });
}

Why this pattern works well

  • It keeps all auth and error handling in one place.
  • You can grow the wrapper endpoint by endpoint instead of trying to generate a client up front.
  • The API already exposes predictable JSON envelopes, so simple TypeScript types go a long way.