Skip to main content
Glama
pylon-client.ts10.5 kB
const PYLON_API_BASE = 'https://api.usepylon.com'; export interface PylonConfig { apiToken: string; } export interface PaginationParams { limit?: number; cursor?: string; } export interface PaginatedResponse<T> { data: T[]; pagination: { cursor: string | null; has_next_page: boolean; }; request_id: string; } export interface SingleResponse<T> { data: T; request_id: string; } export interface Organization { id: string; name: string; } export interface Account { id: string; name: string; domains?: string[]; primary_domain?: string; logo_url?: string; owner_id?: string; channels?: object[]; custom_fields?: object; external_ids?: object[]; tags?: string[]; } export interface Contact { id: string; name: string; email?: string; emails?: string[]; avatar_url?: string; account?: { id: string; name: string }; custom_fields?: object; portal_role?: string; } export interface Issue { id: string; title: string; state: string; priority?: string; body_html?: string; assignee_id?: string; team_id?: string; account_id?: string; contact_id?: string; requester_id?: string; tags?: string[]; created_at?: string; updated_at?: string; customer_portal_visible?: boolean; issue_type?: string; } export interface Message { id: string; message_html: string; author: { avatar_url?: string; name: string; contact?: { email: string; id: string }; user?: { email: string; id: string }; }; is_private: boolean; source: string; thread_id: string; timestamp: string; file_urls?: string[]; email_info?: { from_email: string; to_emails: string[]; cc_emails?: string[]; bcc_emails?: string[]; }; } export interface Tag { id: string; value: string; object_type: 'account' | 'issue' | 'contact'; hex_color?: string; } export interface Team { id: string; name: string; users: { email: string; id: string }[]; } export interface User { id: string; email: string; name?: string; } export class PylonClient { private apiToken: string; constructor(config: PylonConfig) { this.apiToken = config.apiToken; } private async request<T>( method: string, path: string, body?: object, ): Promise<T> { const url = `${PYLON_API_BASE}${path}`; const headers: Record<string, string> = { Authorization: `Bearer ${this.apiToken}`, 'Content-Type': 'application/json', Accept: 'application/json', }; const response = await fetch(url, { method, headers, body: body ? JSON.stringify(body) : undefined, }); if (!response.ok) { const errorText = await response.text(); throw new Error( `Pylon API error: ${response.status} ${response.statusText} - ${errorText}`, ); } return response.json() as Promise<T>; } // Organization async getMe(): Promise<SingleResponse<Organization>> { return this.request<SingleResponse<Organization>>('GET', '/me'); } // Accounts async listAccounts( params?: PaginationParams, ): Promise<PaginatedResponse<Account>> { const searchParams = new URLSearchParams(); if (params?.limit) searchParams.set('limit', params.limit.toString()); if (params?.cursor) searchParams.set('cursor', params.cursor); const query = searchParams.toString(); return this.request<PaginatedResponse<Account>>( 'GET', `/accounts${query ? `?${query}` : ''}`, ); } async getAccount(id: string): Promise<SingleResponse<Account>> { return this.request<SingleResponse<Account>>('GET', `/accounts/${id}`); } async createAccount( data: Partial<Account> & { name: string }, ): Promise<SingleResponse<Account>> { return this.request<SingleResponse<Account>>('POST', '/accounts', data); } async updateAccount( id: string, data: Partial<Account>, ): Promise<SingleResponse<Account>> { return this.request<SingleResponse<Account>>( 'PATCH', `/accounts/${id}`, data, ); } async deleteAccount( id: string, ): Promise<SingleResponse<{ success: boolean }>> { return this.request<SingleResponse<{ success: boolean }>>( 'DELETE', `/accounts/${id}`, ); } async searchAccounts( filter: object, params?: PaginationParams, ): Promise<PaginatedResponse<Account>> { return this.request<PaginatedResponse<Account>>( 'POST', '/accounts/search', { filter, limit: params?.limit, cursor: params?.cursor, }, ); } // Contacts async listContacts( params?: PaginationParams, ): Promise<PaginatedResponse<Contact>> { const searchParams = new URLSearchParams(); if (params?.limit) searchParams.set('limit', params.limit.toString()); if (params?.cursor) searchParams.set('cursor', params.cursor); const query = searchParams.toString(); return this.request<PaginatedResponse<Contact>>( 'GET', `/contacts${query ? `?${query}` : ''}`, ); } async getContact(id: string): Promise<SingleResponse<Contact>> { return this.request<SingleResponse<Contact>>('GET', `/contacts/${id}`); } async createContact( data: Partial<Contact> & { name: string }, ): Promise<SingleResponse<Contact>> { return this.request<SingleResponse<Contact>>('POST', '/contacts', data); } async updateContact( id: string, data: Partial<Contact>, ): Promise<SingleResponse<Contact>> { return this.request<SingleResponse<Contact>>( 'PATCH', `/contacts/${id}`, data, ); } async deleteContact( id: string, ): Promise<SingleResponse<{ success: boolean }>> { return this.request<SingleResponse<{ success: boolean }>>( 'DELETE', `/contacts/${id}`, ); } async searchContacts( filter: object, params?: PaginationParams, ): Promise<PaginatedResponse<Contact>> { return this.request<PaginatedResponse<Contact>>( 'POST', '/contacts/search', { filter, limit: params?.limit, cursor: params?.cursor, }, ); } // Issues async listIssues( startTime: string, endTime: string, ): Promise<PaginatedResponse<Issue>> { const searchParams = new URLSearchParams(); searchParams.set('start_time', startTime); searchParams.set('end_time', endTime); return this.request<PaginatedResponse<Issue>>( 'GET', `/issues?${searchParams.toString()}`, ); } async getIssue(id: string): Promise<SingleResponse<Issue>> { return this.request<SingleResponse<Issue>>('GET', `/issues/${id}`); } async createIssue(data: { title: string; body_html: string; account_id?: string; assignee_id?: string; contact_id?: string; requester_id?: string; user_id?: string; tags?: string[]; attachment_urls?: string[]; custom_fields?: object[]; priority?: 'urgent' | 'high' | 'medium' | 'low'; destination_metadata?: object; }): Promise<SingleResponse<Issue>> { return this.request<SingleResponse<Issue>>('POST', '/issues', data); } async updateIssue( id: string, data: { state?: string; title?: string; tags?: string[]; assignee_id?: string; team_id?: string; account_id?: string; customer_portal_visible?: boolean; priority?: 'urgent' | 'high' | 'medium' | 'low'; }, ): Promise<SingleResponse<Issue>> { return this.request<SingleResponse<Issue>>('PATCH', `/issues/${id}`, data); } async deleteIssue(id: string): Promise<SingleResponse<{ success: boolean }>> { return this.request<SingleResponse<{ success: boolean }>>( 'DELETE', `/issues/${id}`, ); } async searchIssues( filter: object, params?: PaginationParams, ): Promise<PaginatedResponse<Issue>> { return this.request<PaginatedResponse<Issue>>('POST', '/issues/search', { filter, limit: params?.limit, cursor: params?.cursor, }); } async snoozeIssue( id: string, snooze_until: string, ): Promise<SingleResponse<Issue>> { return this.request<SingleResponse<Issue>>('POST', `/issues/${id}/snooze`, { snooze_until, }); } async getIssueFollowers( id: string, ): Promise<PaginatedResponse<{ id: string; email: string }>> { return this.request<PaginatedResponse<{ id: string; email: string }>>( 'GET', `/issues/${id}/followers`, ); } async updateIssueFollowers( id: string, data: { add_user_ids?: string[]; remove_user_ids?: string[] }, ): Promise<SingleResponse<{ success: boolean }>> { return this.request<SingleResponse<{ success: boolean }>>( 'POST', `/issues/${id}/followers`, data, ); } // Messages async redactMessage( issueId: string, messageId: string, ): Promise<SingleResponse<Message>> { return this.request<SingleResponse<Message>>( 'POST', `/issues/${issueId}/messages/${messageId}/redact`, ); } // Tags async listTags(params?: PaginationParams): Promise<PaginatedResponse<Tag>> { const searchParams = new URLSearchParams(); if (params?.limit) searchParams.set('limit', params.limit.toString()); if (params?.cursor) searchParams.set('cursor', params.cursor); const query = searchParams.toString(); return this.request<PaginatedResponse<Tag>>( 'GET', `/tags${query ? `?${query}` : ''}`, ); } async getTag(id: string): Promise<SingleResponse<Tag>> { return this.request<SingleResponse<Tag>>('GET', `/tags/${id}`); } async createTag(data: { value: string; object_type: 'account' | 'issue' | 'contact'; hex_color?: string; }): Promise<SingleResponse<Tag>> { return this.request<SingleResponse<Tag>>('POST', '/tags', data); } async updateTag( id: string, data: { value?: string; hex_color?: string }, ): Promise<SingleResponse<Tag>> { return this.request<SingleResponse<Tag>>('PATCH', `/tags/${id}`, data); } async deleteTag(id: string): Promise<SingleResponse<{ success: boolean }>> { return this.request<SingleResponse<{ success: boolean }>>( 'DELETE', `/tags/${id}`, ); } // Teams async listTeams(params?: PaginationParams): Promise<PaginatedResponse<Team>> { const searchParams = new URLSearchParams(); if (params?.limit) searchParams.set('limit', params.limit.toString()); if (params?.cursor) searchParams.set('cursor', params.cursor); const query = searchParams.toString(); return this.request<PaginatedResponse<Team>>( 'GET', `/teams${query ? `?${query}` : ''}`, ); } async getTeam(id: string): Promise<SingleResponse<Team>> { return this.request<SingleResponse<Team>>('GET', `/teams/${id}`); } async createTeam(data: { name?: string; user_ids?: string[]; }): Promise<SingleResponse<Team>> { return this.request<SingleResponse<Team>>('POST', '/teams', data); } async updateTeam( id: string, data: { name?: string; user_ids?: string[] }, ): Promise<SingleResponse<Team>> { return this.request<SingleResponse<Team>>('PATCH', `/teams/${id}`, data); } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JustinBeckwith/pylon-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server