Features: - 400+ tools covering entire GoHighLevel API - Contact management, conversations, opportunities, calendars - Invoices, payments, products, store management - Social media, email marketing, workflows, and more - Self-host or use managed solution at mcp.localbosses.org
6858 lines
204 KiB
TypeScript
6858 lines
204 KiB
TypeScript
/**
|
|
* GoHighLevel API Client
|
|
* Implements exact API endpoints from OpenAPI specifications v2021-07-28 (Contacts) and v2021-04-15 (Conversations)
|
|
*/
|
|
|
|
import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';
|
|
import {
|
|
GHLConfig,
|
|
GHLContact,
|
|
GHLCreateContactRequest,
|
|
GHLSearchContactsRequest,
|
|
GHLSearchContactsResponse,
|
|
GHLContactTagsRequest,
|
|
GHLContactTagsResponse,
|
|
GHLApiResponse,
|
|
GHLErrorResponse,
|
|
GHLTask,
|
|
GHLNote,
|
|
// Conversation types
|
|
GHLConversation,
|
|
GHLMessage,
|
|
GHLSendMessageRequest,
|
|
GHLSendMessageResponse,
|
|
GHLSearchConversationsRequest,
|
|
GHLSearchConversationsResponse,
|
|
GHLGetMessagesResponse,
|
|
GHLCreateConversationRequest,
|
|
GHLCreateConversationResponse,
|
|
GHLUpdateConversationRequest,
|
|
// Blog types
|
|
GHLBlogPost,
|
|
GHLCreateBlogPostRequest,
|
|
GHLUpdateBlogPostRequest,
|
|
GHLBlogPostCreateResponse,
|
|
GHLBlogPostUpdateResponse,
|
|
GHLBlogPostListResponse,
|
|
GHLBlogAuthor,
|
|
GHLBlogAuthorsResponse,
|
|
GHLBlogCategory,
|
|
GHLBlogCategoriesResponse,
|
|
GHLBlogSite,
|
|
GHLBlogSitesResponse,
|
|
GHLUrlSlugCheckResponse,
|
|
GHLGetBlogPostsRequest,
|
|
GHLGetBlogAuthorsRequest,
|
|
GHLGetBlogCategoriesRequest,
|
|
GHLGetBlogSitesRequest,
|
|
GHLCheckUrlSlugRequest,
|
|
GHLSearchOpportunitiesRequest,
|
|
GHLSearchOpportunitiesResponse,
|
|
GHLGetPipelinesResponse,
|
|
GHLOpportunity,
|
|
GHLCreateOpportunityRequest,
|
|
GHLUpdateOpportunityRequest,
|
|
GHLOpportunityStatus,
|
|
GHLUpdateOpportunityStatusRequest,
|
|
GHLUpsertOpportunityRequest,
|
|
GHLUpsertOpportunityResponse,
|
|
GHLGetCalendarGroupsResponse,
|
|
GHLCreateCalendarGroupRequest,
|
|
GHLCalendarGroup,
|
|
GHLGetCalendarsResponse,
|
|
GHLCreateCalendarRequest,
|
|
GHLCalendar,
|
|
GHLUpdateCalendarRequest,
|
|
GHLGetCalendarEventsRequest,
|
|
GHLGetCalendarEventsResponse,
|
|
GHLGetFreeSlotsRequest,
|
|
GHLGetFreeSlotsResponse,
|
|
GHLCreateAppointmentRequest,
|
|
GHLCalendarEvent,
|
|
GHLUpdateAppointmentRequest,
|
|
GHLCreateBlockSlotRequest,
|
|
GHLBlockSlotResponse,
|
|
GHLUpdateBlockSlotRequest,
|
|
GHLEmailCampaignsResponse,
|
|
MCPGetEmailCampaignsParams,
|
|
MCPCreateEmailTemplateParams,
|
|
MCPGetEmailTemplatesParams,
|
|
MCPUpdateEmailTemplateParams,
|
|
MCPDeleteEmailTemplateParams,
|
|
GHLEmailTemplate,
|
|
// Location types
|
|
GHLLocationSearchResponse,
|
|
GHLLocationDetailsResponse,
|
|
GHLLocationDetailed,
|
|
GHLCreateLocationRequest,
|
|
GHLUpdateLocationRequest,
|
|
GHLLocationDeleteResponse,
|
|
GHLLocationTagsResponse,
|
|
GHLLocationTagResponse,
|
|
GHLLocationTagRequest,
|
|
GHLLocationTagDeleteResponse,
|
|
GHLLocationTaskSearchRequest,
|
|
GHLLocationTaskSearchResponse,
|
|
GHLLocationCustomFieldsResponse,
|
|
GHLLocationCustomFieldResponse,
|
|
GHLCreateCustomFieldRequest,
|
|
GHLUpdateCustomFieldRequest,
|
|
GHLCustomFieldDeleteResponse,
|
|
GHLFileUploadRequest,
|
|
GHLFileUploadResponse,
|
|
GHLLocationCustomValuesResponse,
|
|
GHLLocationCustomValueResponse,
|
|
GHLCustomValueRequest,
|
|
GHLCustomValueDeleteResponse,
|
|
GHLLocationTemplatesResponse,
|
|
// Email ISV types
|
|
GHLEmailVerificationRequest,
|
|
GHLEmailVerificationResponse,
|
|
// Additional Contact types
|
|
GHLAppointment,
|
|
GHLUpsertContactResponse,
|
|
GHLBulkTagsResponse,
|
|
GHLBulkBusinessResponse,
|
|
GHLFollowersResponse,
|
|
GHLCampaign,
|
|
GHLWorkflow,
|
|
// Additional Conversation/Message types
|
|
GHLEmailMessage,
|
|
GHLProcessInboundMessageRequest,
|
|
GHLProcessOutboundMessageRequest,
|
|
GHLProcessMessageResponse,
|
|
GHLCancelScheduledResponse,
|
|
GHLMessageRecordingResponse,
|
|
GHLMessageTranscription,
|
|
GHLMessageTranscriptionResponse,
|
|
GHLLiveChatTypingRequest,
|
|
GHLLiveChatTypingResponse,
|
|
GHLUploadFilesRequest,
|
|
GHLUploadFilesResponse,
|
|
GHLUpdateMessageStatusRequest,
|
|
// Social Media Posting API types
|
|
GHLSocialPlatform,
|
|
GHLSearchPostsRequest,
|
|
GHLSearchPostsResponse,
|
|
GHLCreatePostRequest,
|
|
GHLCreatePostResponse,
|
|
GHLUpdatePostRequest,
|
|
GHLGetPostResponse,
|
|
GHLBulkDeletePostsRequest,
|
|
GHLBulkDeleteResponse,
|
|
GHLGetAccountsResponse,
|
|
GHLUploadCSVRequest,
|
|
GHLUploadCSVResponse,
|
|
GHLGetUploadStatusResponse,
|
|
GHLSetAccountsRequest,
|
|
GHLCSVFinalizeRequest,
|
|
GHLGetCategoriesResponse,
|
|
GHLGetCategoryResponse,
|
|
GHLGetTagsResponse,
|
|
GHLGetTagsByIdsRequest,
|
|
GHLGetTagsByIdsResponse,
|
|
GHLOAuthStartResponse,
|
|
GHLGetGoogleLocationsResponse,
|
|
GHLAttachGMBLocationRequest,
|
|
GHLGetFacebookPagesResponse,
|
|
GHLAttachFBAccountRequest,
|
|
GHLGetInstagramAccountsResponse,
|
|
GHLAttachIGAccountRequest,
|
|
GHLGetLinkedInAccountsResponse,
|
|
GHLAttachLinkedInAccountRequest,
|
|
GHLGetTwitterAccountsResponse,
|
|
GHLAttachTwitterAccountRequest,
|
|
GHLGetTikTokAccountsResponse,
|
|
GHLAttachTikTokAccountRequest,
|
|
GHLCSVImport,
|
|
GHLSocialPost,
|
|
GHLSocialAccount,
|
|
GHLValidateGroupSlugResponse,
|
|
GHLGroupSuccessResponse,
|
|
GHLGroupStatusUpdateRequest,
|
|
GHLUpdateCalendarGroupRequest,
|
|
GHLGetAppointmentNotesResponse,
|
|
GHLCreateAppointmentNoteRequest,
|
|
GHLAppointmentNoteResponse,
|
|
GHLUpdateAppointmentNoteRequest,
|
|
GHLDeleteAppointmentNoteResponse,
|
|
GHLCalendarResource,
|
|
GHLCreateCalendarResourceRequest,
|
|
GHLCalendarResourceResponse,
|
|
GHLCalendarResourceByIdResponse,
|
|
GHLUpdateCalendarResourceRequest,
|
|
GHLResourceDeleteResponse,
|
|
GHLCalendarNotification,
|
|
GHLCreateCalendarNotificationRequest,
|
|
GHLUpdateCalendarNotificationRequest,
|
|
GHLCalendarNotificationDeleteResponse,
|
|
GHLGetCalendarNotificationsRequest,
|
|
GHLGetBlockedSlotsRequest,
|
|
GHLGetMediaFilesRequest,
|
|
GHLGetMediaFilesResponse,
|
|
GHLUploadMediaFileRequest,
|
|
GHLUploadMediaFileResponse,
|
|
GHLDeleteMediaRequest,
|
|
GHLDeleteMediaResponse,
|
|
// Custom Objects API types
|
|
GHLGetObjectSchemaRequest,
|
|
GHLGetObjectSchemaResponse,
|
|
GHLObjectListResponse,
|
|
GHLCreateObjectSchemaRequest,
|
|
GHLObjectSchemaResponse,
|
|
GHLUpdateObjectSchemaRequest,
|
|
GHLCreateObjectRecordRequest,
|
|
GHLObjectRecordResponse,
|
|
GHLDetailedObjectRecordResponse,
|
|
GHLUpdateObjectRecordRequest,
|
|
GHLObjectRecordDeleteResponse,
|
|
GHLSearchObjectRecordsRequest,
|
|
GHLSearchObjectRecordsResponse,
|
|
// Associations API types
|
|
GHLAssociation,
|
|
GHLRelation,
|
|
GHLCreateAssociationRequest,
|
|
GHLUpdateAssociationRequest,
|
|
GHLCreateRelationRequest,
|
|
GHLGetAssociationsRequest,
|
|
GHLGetRelationsByRecordRequest,
|
|
GHLGetAssociationByKeyRequest,
|
|
GHLGetAssociationByObjectKeyRequest,
|
|
GHLDeleteRelationRequest,
|
|
GHLAssociationResponse,
|
|
GHLDeleteAssociationResponse,
|
|
GHLGetAssociationsResponse,
|
|
GHLGetRelationsResponse,
|
|
// Custom Fields V2 API types
|
|
GHLV2CustomField,
|
|
GHLV2CustomFieldFolder,
|
|
GHLV2CreateCustomFieldRequest,
|
|
GHLV2UpdateCustomFieldRequest,
|
|
GHLV2CreateCustomFieldFolderRequest,
|
|
GHLV2UpdateCustomFieldFolderRequest,
|
|
GHLV2GetCustomFieldsByObjectKeyRequest,
|
|
GHLV2DeleteCustomFieldFolderRequest,
|
|
GHLV2CustomFieldResponse,
|
|
GHLV2CustomFieldsResponse,
|
|
GHLV2CustomFieldFolderResponse,
|
|
GHLV2DeleteCustomFieldResponse,
|
|
// Workflows API types
|
|
GHLGetWorkflowsRequest,
|
|
GHLGetWorkflowsResponse,
|
|
// Surveys API types
|
|
GHLGetSurveysRequest,
|
|
GHLGetSurveysResponse,
|
|
GHLGetSurveySubmissionsRequest,
|
|
GHLGetSurveySubmissionsResponse,
|
|
// Store API types
|
|
GHLCreateShippingZoneRequest,
|
|
GHLCreateShippingZoneResponse,
|
|
GHLListShippingZonesResponse,
|
|
GHLGetShippingZonesRequest,
|
|
GHLGetShippingZoneResponse,
|
|
GHLUpdateShippingZoneRequest,
|
|
GHLUpdateShippingZoneResponse,
|
|
GHLDeleteShippingZoneRequest,
|
|
GHLDeleteShippingZoneResponse,
|
|
GHLGetAvailableShippingRatesRequest,
|
|
GHLGetAvailableShippingRatesResponse,
|
|
GHLCreateShippingRateRequest,
|
|
GHLCreateShippingRateResponse,
|
|
GHLListShippingRatesResponse,
|
|
GHLGetShippingRatesRequest,
|
|
GHLGetShippingRateResponse,
|
|
GHLUpdateShippingRateRequest,
|
|
GHLUpdateShippingRateResponse,
|
|
GHLDeleteShippingRateRequest,
|
|
GHLDeleteShippingRateResponse,
|
|
GHLCreateShippingCarrierRequest,
|
|
GHLCreateShippingCarrierResponse,
|
|
GHLListShippingCarriersResponse,
|
|
GHLGetShippingCarriersRequest,
|
|
GHLGetShippingCarrierResponse,
|
|
GHLUpdateShippingCarrierRequest,
|
|
GHLUpdateShippingCarrierResponse,
|
|
GHLDeleteShippingCarrierRequest,
|
|
GHLDeleteShippingCarrierResponse,
|
|
GHLCreateStoreSettingRequest,
|
|
GHLCreateStoreSettingResponse,
|
|
GHLGetStoreSettingRequest,
|
|
GHLGetStoreSettingResponse,
|
|
GHLCreateProductRequest,
|
|
GHLCreateProductResponse,
|
|
GHLUpdateProductRequest,
|
|
GHLUpdateProductResponse,
|
|
GHLGetProductRequest,
|
|
GHLGetProductResponse,
|
|
GHLListProductsRequest,
|
|
GHLListProductsResponse,
|
|
GHLDeleteProductRequest,
|
|
GHLDeleteProductResponse,
|
|
GHLBulkUpdateRequest,
|
|
GHLBulkUpdateResponse,
|
|
GHLCreatePriceRequest,
|
|
GHLCreatePriceResponse,
|
|
GHLUpdatePriceRequest,
|
|
GHLUpdatePriceResponse,
|
|
GHLGetPriceRequest,
|
|
GHLGetPriceResponse,
|
|
GHLListPricesRequest,
|
|
GHLListPricesResponse,
|
|
GHLDeletePriceRequest,
|
|
GHLDeletePriceResponse,
|
|
GHLListInventoryRequest,
|
|
GHLListInventoryResponse,
|
|
GHLUpdateInventoryRequest,
|
|
GHLUpdateInventoryResponse,
|
|
GHLGetProductStoreStatsRequest,
|
|
GHLGetProductStoreStatsResponse,
|
|
GHLUpdateProductStoreRequest,
|
|
GHLUpdateProductStoreResponse,
|
|
GHLCreateProductCollectionRequest,
|
|
GHLCreateCollectionResponse,
|
|
GHLUpdateProductCollectionRequest,
|
|
GHLUpdateProductCollectionResponse,
|
|
GHLGetProductCollectionRequest,
|
|
GHLDefaultCollectionResponse,
|
|
GHLListProductCollectionsRequest,
|
|
GHLListCollectionResponse,
|
|
GHLDeleteProductCollectionRequest,
|
|
GHLDeleteProductCollectionResponse,
|
|
GHLListProductReviewsRequest,
|
|
GHLListProductReviewsResponse,
|
|
GHLGetReviewsCountRequest,
|
|
GHLCountReviewsByStatusResponse,
|
|
GHLUpdateProductReviewRequest,
|
|
GHLUpdateProductReviewsResponse,
|
|
GHLDeleteProductReviewRequest,
|
|
GHLDeleteProductReviewResponse,
|
|
GHLBulkUpdateProductReviewsRequest,
|
|
// Invoice API types
|
|
CreateInvoiceTemplateDto,
|
|
CreateInvoiceTemplateResponseDto,
|
|
UpdateInvoiceTemplateDto,
|
|
UpdateInvoiceTemplateResponseDto,
|
|
DeleteInvoiceTemplateResponseDto,
|
|
ListTemplatesResponse,
|
|
InvoiceTemplate,
|
|
UpdateInvoiceLateFeesConfigurationDto,
|
|
UpdatePaymentMethodsConfigurationDto,
|
|
CreateInvoiceScheduleDto,
|
|
CreateInvoiceScheduleResponseDto,
|
|
UpdateInvoiceScheduleDto,
|
|
UpdateInvoiceScheduleResponseDto,
|
|
DeleteInvoiceScheduleResponseDto,
|
|
ListSchedulesResponse,
|
|
GetScheduleResponseDto,
|
|
ScheduleInvoiceScheduleDto,
|
|
ScheduleInvoiceScheduleResponseDto,
|
|
AutoPaymentScheduleDto,
|
|
AutoPaymentInvoiceScheduleResponseDto,
|
|
CancelInvoiceScheduleDto,
|
|
CancelInvoiceScheduleResponseDto,
|
|
UpdateAndScheduleInvoiceScheduleResponseDto,
|
|
Text2PayDto,
|
|
Text2PayInvoiceResponseDto,
|
|
GenerateInvoiceNumberResponse,
|
|
GetInvoiceResponseDto,
|
|
UpdateInvoiceDto,
|
|
UpdateInvoiceResponseDto,
|
|
DeleteInvoiceResponseDto,
|
|
VoidInvoiceDto,
|
|
VoidInvoiceResponseDto,
|
|
SendInvoiceDto,
|
|
SendInvoicesResponseDto,
|
|
RecordPaymentDto,
|
|
RecordPaymentResponseDto,
|
|
PatchInvoiceStatsLastViewedDto,
|
|
CreateEstimatesDto,
|
|
EstimateResponseDto,
|
|
UpdateEstimateDto,
|
|
GenerateEstimateNumberResponse,
|
|
SendEstimateDto,
|
|
CreateInvoiceFromEstimateDto,
|
|
CreateInvoiceFromEstimateResponseDto,
|
|
ListEstimatesResponseDto,
|
|
EstimateIdParam,
|
|
ListEstimateTemplateResponseDto,
|
|
EstimateTemplatesDto,
|
|
EstimateTemplateResponseDto,
|
|
CreateInvoiceDto,
|
|
CreateInvoiceResponseDto,
|
|
ListInvoicesResponseDto,
|
|
AltDto
|
|
} from '../types/ghl-types.js';
|
|
|
|
/**
|
|
* GoHighLevel API Client
|
|
* Handles all API communication with GHL services
|
|
*/
|
|
export class GHLApiClient {
|
|
private axiosInstance: AxiosInstance;
|
|
private config: GHLConfig;
|
|
|
|
constructor(config: GHLConfig) {
|
|
this.config = config;
|
|
|
|
// Create axios instance with base configuration
|
|
this.axiosInstance = axios.create({
|
|
baseURL: config.baseUrl,
|
|
headers: {
|
|
'Authorization': `Bearer ${config.accessToken}`,
|
|
'Version': config.version,
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
},
|
|
timeout: 30000 // 30 second timeout
|
|
});
|
|
|
|
// Add request interceptor for logging
|
|
this.axiosInstance.interceptors.request.use(
|
|
(config) => {
|
|
process.stderr.write(`[GHL API] ${config.method?.toUpperCase()} ${config.url}\n`);
|
|
return config;
|
|
},
|
|
(error) => {
|
|
console.error('[GHL API] Request error:', error);
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Add response interceptor for error handling
|
|
this.axiosInstance.interceptors.response.use(
|
|
(response) => {
|
|
process.stderr.write(`[GHL API] Response ${response.status}: ${response.config.url}\n`);
|
|
return response;
|
|
},
|
|
(error: AxiosError<GHLErrorResponse>) => {
|
|
console.error('[GHL API] Response error:', {
|
|
status: error.response?.status,
|
|
message: error.response?.data?.message,
|
|
url: error.config?.url
|
|
});
|
|
return Promise.reject(this.handleApiError(error));
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle API errors and convert to standardized format
|
|
*/
|
|
private handleApiError(error: AxiosError<GHLErrorResponse>): Error {
|
|
const status = error.response?.status || 500;
|
|
const message = error.response?.data?.message || error.message || 'Unknown error';
|
|
const errorMessage = Array.isArray(message) ? message.join(', ') : message;
|
|
|
|
return new Error(`GHL API Error (${status}): ${errorMessage}`);
|
|
}
|
|
|
|
/**
|
|
* Wrap API responses in standardized format
|
|
*/
|
|
private wrapResponse<T>(data: T): GHLApiResponse<T> {
|
|
return {
|
|
success: true,
|
|
data
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create custom headers for different API versions
|
|
*/
|
|
private getConversationHeaders() {
|
|
return {
|
|
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
'Version': '2021-04-15', // Conversations API uses different version
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
};
|
|
}
|
|
|
|
/**
|
|
* CONTACTS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create a new contact
|
|
* POST /contacts/
|
|
*/
|
|
async createContact(contactData: GHLCreateContactRequest): Promise<GHLApiResponse<GHLContact>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...contactData,
|
|
locationId: contactData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ contact: GHLContact }> = await this.axiosInstance.post(
|
|
'/contacts/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data.contact);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get contact by ID
|
|
* GET /contacts/{contactId}
|
|
*/
|
|
async getContact(contactId: string): Promise<GHLApiResponse<GHLContact>> {
|
|
try {
|
|
const response: AxiosResponse<{ contact: GHLContact }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.contact);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update existing contact
|
|
* PUT /contacts/{contactId}
|
|
*/
|
|
async updateContact(contactId: string, updates: Partial<GHLCreateContactRequest>): Promise<GHLApiResponse<GHLContact>> {
|
|
try {
|
|
const response: AxiosResponse<{ contact: GHLContact; succeded: boolean }> = await this.axiosInstance.put(
|
|
`/contacts/${contactId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data.contact);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete contact
|
|
* DELETE /contacts/{contactId}
|
|
*/
|
|
async deleteContact(contactId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search contacts with advanced filters
|
|
* POST /contacts/search
|
|
*/
|
|
async searchContacts(searchParams: GHLSearchContactsRequest): Promise<GHLApiResponse<GHLSearchContactsResponse>> {
|
|
try {
|
|
// Build minimal request body with only required/supported parameters
|
|
// Start with just locationId and pageLimit as per API requirements
|
|
const payload: any = {
|
|
locationId: searchParams.locationId || this.config.locationId,
|
|
pageLimit: searchParams.limit || 25
|
|
};
|
|
|
|
// Only add optional parameters if they have valid values
|
|
if (searchParams.query && searchParams.query.trim()) {
|
|
payload.query = searchParams.query.trim();
|
|
}
|
|
|
|
if (searchParams.startAfterId && searchParams.startAfterId.trim()) {
|
|
payload.startAfterId = searchParams.startAfterId.trim();
|
|
}
|
|
|
|
if (searchParams.startAfter && typeof searchParams.startAfter === 'number') {
|
|
payload.startAfter = searchParams.startAfter;
|
|
}
|
|
|
|
// Only add filters if we have valid filter values
|
|
if (searchParams.filters) {
|
|
const filters: any = {};
|
|
let hasFilters = false;
|
|
|
|
if (searchParams.filters.email && typeof searchParams.filters.email === 'string' && searchParams.filters.email.trim()) {
|
|
filters.email = searchParams.filters.email.trim();
|
|
hasFilters = true;
|
|
}
|
|
|
|
if (searchParams.filters.phone && typeof searchParams.filters.phone === 'string' && searchParams.filters.phone.trim()) {
|
|
filters.phone = searchParams.filters.phone.trim();
|
|
hasFilters = true;
|
|
}
|
|
|
|
if (searchParams.filters.tags && Array.isArray(searchParams.filters.tags) && searchParams.filters.tags.length > 0) {
|
|
filters.tags = searchParams.filters.tags;
|
|
hasFilters = true;
|
|
}
|
|
|
|
if (searchParams.filters.dateAdded && typeof searchParams.filters.dateAdded === 'object') {
|
|
filters.dateAdded = searchParams.filters.dateAdded;
|
|
hasFilters = true;
|
|
}
|
|
|
|
// Only add filters object if we have actual filters
|
|
if (hasFilters) {
|
|
payload.filters = filters;
|
|
}
|
|
}
|
|
|
|
process.stderr.write(`[GHL API] Search contacts payload: ${JSON.stringify(payload, null, 2)}\n`);
|
|
|
|
const response: AxiosResponse<GHLSearchContactsResponse> = await this.axiosInstance.post(
|
|
'/contacts/search',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
const axiosError = error as AxiosError<GHLErrorResponse>;
|
|
process.stderr.write(`[GHL API] Search contacts error: ${JSON.stringify({
|
|
status: axiosError.response?.status,
|
|
statusText: axiosError.response?.statusText,
|
|
data: axiosError.response?.data,
|
|
message: axiosError.message
|
|
}, null, 2)}\n`);
|
|
|
|
const handledError = this.handleApiError(axiosError);
|
|
return {
|
|
success: false,
|
|
error: {
|
|
message: handledError.message,
|
|
statusCode: axiosError.response?.status || 500,
|
|
details: axiosError.response?.data
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get duplicate contact by email or phone
|
|
* GET /contacts/search/duplicate
|
|
*/
|
|
async getDuplicateContact(email?: string, phone?: string): Promise<GHLApiResponse<GHLContact | null>> {
|
|
try {
|
|
const params: any = {
|
|
locationId: this.config.locationId
|
|
};
|
|
|
|
if (email) params.email = encodeURIComponent(email);
|
|
if (phone) params.number = encodeURIComponent(phone);
|
|
|
|
const response: AxiosResponse<{ contact?: GHLContact }> = await this.axiosInstance.get(
|
|
'/contacts/search/duplicate',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data.contact || null);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add tags to contact
|
|
* POST /contacts/{contactId}/tags
|
|
*/
|
|
async addContactTags(contactId: string, tags: string[]): Promise<GHLApiResponse<GHLContactTagsResponse>> {
|
|
try {
|
|
const payload: GHLContactTagsRequest = { tags };
|
|
|
|
const response: AxiosResponse<GHLContactTagsResponse> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/tags`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove tags from contact
|
|
* DELETE /contacts/{contactId}/tags
|
|
*/
|
|
async removeContactTags(contactId: string, tags: string[]): Promise<GHLApiResponse<GHLContactTagsResponse>> {
|
|
try {
|
|
const payload: GHLContactTagsRequest = { tags };
|
|
|
|
const response: AxiosResponse<GHLContactTagsResponse> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/tags`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* CONVERSATIONS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Search conversations with filters
|
|
* GET /conversations/search
|
|
*/
|
|
async searchConversations(searchParams: GHLSearchConversationsRequest): Promise<GHLApiResponse<GHLSearchConversationsResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const params = {
|
|
...searchParams,
|
|
locationId: searchParams.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLSearchConversationsResponse> = await this.axiosInstance.get(
|
|
'/conversations/search',
|
|
{
|
|
params,
|
|
headers: this.getConversationHeaders()
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get conversation by ID
|
|
* GET /conversations/{conversationId}
|
|
*/
|
|
async getConversation(conversationId: string): Promise<GHLApiResponse<GHLConversation>> {
|
|
try {
|
|
const response: AxiosResponse<GHLConversation> = await this.axiosInstance.get(
|
|
`/conversations/${conversationId}`,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new conversation
|
|
* POST /conversations/
|
|
*/
|
|
async createConversation(conversationData: GHLCreateConversationRequest): Promise<GHLApiResponse<GHLCreateConversationResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...conversationData,
|
|
locationId: conversationData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ success: boolean; conversation: GHLCreateConversationResponse }> = await this.axiosInstance.post(
|
|
'/conversations/',
|
|
payload,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data.conversation);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update conversation
|
|
* PUT /conversations/{conversationId}
|
|
*/
|
|
async updateConversation(conversationId: string, updates: GHLUpdateConversationRequest): Promise<GHLApiResponse<GHLConversation>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...updates,
|
|
locationId: updates.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ success: boolean; conversation: GHLConversation }> = await this.axiosInstance.put(
|
|
`/conversations/${conversationId}`,
|
|
payload,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data.conversation);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete conversation
|
|
* DELETE /conversations/{conversationId}
|
|
*/
|
|
async deleteConversation(conversationId: string): Promise<GHLApiResponse<{ success: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ success: boolean }> = await this.axiosInstance.delete(
|
|
`/conversations/${conversationId}`,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get messages from a conversation
|
|
* GET /conversations/{conversationId}/messages
|
|
*/
|
|
async getConversationMessages(
|
|
conversationId: string,
|
|
options?: {
|
|
lastMessageId?: string;
|
|
limit?: number;
|
|
type?: string;
|
|
}
|
|
): Promise<GHLApiResponse<GHLGetMessagesResponse>> {
|
|
try {
|
|
const params: any = {};
|
|
if (options?.lastMessageId) params.lastMessageId = options.lastMessageId;
|
|
if (options?.limit) params.limit = options.limit;
|
|
if (options?.type) params.type = options.type;
|
|
|
|
const response: AxiosResponse<GHLGetMessagesResponse> = await this.axiosInstance.get(
|
|
`/conversations/${conversationId}/messages`,
|
|
{
|
|
params,
|
|
headers: this.getConversationHeaders()
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get message by ID
|
|
* GET /conversations/messages/{id}
|
|
*/
|
|
async getMessage(messageId: string): Promise<GHLApiResponse<GHLMessage>> {
|
|
try {
|
|
const response: AxiosResponse<GHLMessage> = await this.axiosInstance.get(
|
|
`/conversations/messages/${messageId}`,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send a new message (SMS, Email, etc.)
|
|
* POST /conversations/messages
|
|
*/
|
|
async sendMessage(messageData: GHLSendMessageRequest): Promise<GHLApiResponse<GHLSendMessageResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLSendMessageResponse> = await this.axiosInstance.post(
|
|
'/conversations/messages',
|
|
messageData,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send SMS message to a contact
|
|
* Convenience method for sending SMS
|
|
*/
|
|
async sendSMS(contactId: string, message: string, fromNumber?: string): Promise<GHLApiResponse<GHLSendMessageResponse>> {
|
|
try {
|
|
const messageData: GHLSendMessageRequest = {
|
|
type: 'SMS',
|
|
contactId,
|
|
message,
|
|
fromNumber
|
|
};
|
|
|
|
return await this.sendMessage(messageData);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send Email message to a contact
|
|
* Convenience method for sending Email
|
|
*/
|
|
async sendEmail(
|
|
contactId: string,
|
|
subject: string,
|
|
message?: string,
|
|
html?: string,
|
|
options?: {
|
|
emailFrom?: string;
|
|
emailTo?: string;
|
|
emailCc?: string[];
|
|
emailBcc?: string[];
|
|
attachments?: string[];
|
|
}
|
|
): Promise<GHLApiResponse<GHLSendMessageResponse>> {
|
|
try {
|
|
const messageData: GHLSendMessageRequest = {
|
|
type: 'Email',
|
|
contactId,
|
|
subject,
|
|
message,
|
|
html,
|
|
...options
|
|
};
|
|
|
|
return await this.sendMessage(messageData);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* BLOG API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get all blog sites for a location
|
|
* GET /blogs/site/all
|
|
*/
|
|
async getBlogSites(params: GHLGetBlogSitesRequest): Promise<GHLApiResponse<GHLBlogSitesResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
skip: params.skip,
|
|
limit: params.limit,
|
|
...(params.searchTerm && { searchTerm: params.searchTerm })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogSitesResponse> = await this.axiosInstance.get(
|
|
'/blogs/site/all',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get blog posts for a specific blog
|
|
* GET /blogs/posts/all
|
|
*/
|
|
async getBlogPosts(params: GHLGetBlogPostsRequest): Promise<GHLApiResponse<GHLBlogPostListResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
blogId: params.blogId,
|
|
limit: params.limit,
|
|
offset: params.offset,
|
|
...(params.searchTerm && { searchTerm: params.searchTerm }),
|
|
...(params.status && { status: params.status })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogPostListResponse> = await this.axiosInstance.get(
|
|
'/blogs/posts/all',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new blog post
|
|
* POST /blogs/posts
|
|
*/
|
|
async createBlogPost(postData: GHLCreateBlogPostRequest): Promise<GHLApiResponse<GHLBlogPostCreateResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...postData,
|
|
locationId: postData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogPostCreateResponse> = await this.axiosInstance.post(
|
|
'/blogs/posts',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update an existing blog post
|
|
* PUT /blogs/posts/{postId}
|
|
*/
|
|
async updateBlogPost(postId: string, postData: GHLUpdateBlogPostRequest): Promise<GHLApiResponse<GHLBlogPostUpdateResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...postData,
|
|
locationId: postData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogPostUpdateResponse> = await this.axiosInstance.put(
|
|
`/blogs/posts/${postId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all blog authors for a location
|
|
* GET /blogs/authors
|
|
*/
|
|
async getBlogAuthors(params: GHLGetBlogAuthorsRequest): Promise<GHLApiResponse<GHLBlogAuthorsResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
limit: params.limit,
|
|
offset: params.offset
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogAuthorsResponse> = await this.axiosInstance.get(
|
|
'/blogs/authors',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all blog categories for a location
|
|
* GET /blogs/categories
|
|
*/
|
|
async getBlogCategories(params: GHLGetBlogCategoriesRequest): Promise<GHLApiResponse<GHLBlogCategoriesResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
limit: params.limit,
|
|
offset: params.offset
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlogCategoriesResponse> = await this.axiosInstance.get(
|
|
'/blogs/categories',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a URL slug exists (for validation before creating/updating posts)
|
|
* GET /blogs/posts/url-slug-exists
|
|
*/
|
|
async checkUrlSlugExists(params: GHLCheckUrlSlugRequest): Promise<GHLApiResponse<GHLUrlSlugCheckResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
urlSlug: params.urlSlug,
|
|
...(params.postId && { postId: params.postId })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUrlSlugCheckResponse> = await this.axiosInstance.get(
|
|
'/blogs/posts/url-slug-exists',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TASKS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get all tasks for a contact
|
|
* GET /contacts/{contactId}/tasks
|
|
*/
|
|
async getContactTasks(contactId: string): Promise<GHLApiResponse<GHLTask[]>> {
|
|
try {
|
|
const response: AxiosResponse<{ tasks: GHLTask[] }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}/tasks`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.tasks);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create task for contact
|
|
* POST /contacts/{contactId}/tasks
|
|
*/
|
|
async createContactTask(contactId: string, taskData: Omit<GHLTask, 'id' | 'contactId'>): Promise<GHLApiResponse<GHLTask>> {
|
|
try {
|
|
const response: AxiosResponse<{ task: GHLTask }> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/tasks`,
|
|
taskData
|
|
);
|
|
|
|
return this.wrapResponse(response.data.task);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* NOTES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get all notes for a contact
|
|
* GET /contacts/{contactId}/notes
|
|
*/
|
|
async getContactNotes(contactId: string): Promise<GHLApiResponse<GHLNote[]>> {
|
|
try {
|
|
const response: AxiosResponse<{ notes: GHLNote[] }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}/notes`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.notes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create note for contact
|
|
* POST /contacts/{contactId}/notes
|
|
*/
|
|
async createContactNote(contactId: string, noteData: Omit<GHLNote, 'id' | 'contactId' | 'dateAdded'>): Promise<GHLApiResponse<GHLNote>> {
|
|
try {
|
|
const response: AxiosResponse<{ note: GHLNote }> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/notes`,
|
|
noteData
|
|
);
|
|
|
|
return this.wrapResponse(response.data.note);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ADDITIONAL CONTACT API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get a specific task for a contact
|
|
* GET /contacts/{contactId}/tasks/{taskId}
|
|
*/
|
|
async getContactTask(contactId: string, taskId: string): Promise<GHLApiResponse<GHLTask>> {
|
|
try {
|
|
const response: AxiosResponse<{ task: GHLTask }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}/tasks/${taskId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.task);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a task for a contact
|
|
* PUT /contacts/{contactId}/tasks/{taskId}
|
|
*/
|
|
async updateContactTask(contactId: string, taskId: string, updates: Partial<GHLTask>): Promise<GHLApiResponse<GHLTask>> {
|
|
try {
|
|
const response: AxiosResponse<{ task: GHLTask }> = await this.axiosInstance.put(
|
|
`/contacts/${contactId}/tasks/${taskId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data.task);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a task for a contact
|
|
* DELETE /contacts/{contactId}/tasks/{taskId}
|
|
*/
|
|
async deleteContactTask(contactId: string, taskId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/tasks/${taskId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update task completion status
|
|
* PUT /contacts/{contactId}/tasks/{taskId}/completed
|
|
*/
|
|
async updateTaskCompletion(contactId: string, taskId: string, completed: boolean): Promise<GHLApiResponse<GHLTask>> {
|
|
try {
|
|
const response: AxiosResponse<{ task: GHLTask }> = await this.axiosInstance.put(
|
|
`/contacts/${contactId}/tasks/${taskId}/completed`,
|
|
{ completed }
|
|
);
|
|
|
|
return this.wrapResponse(response.data.task);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a specific note for a contact
|
|
* GET /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async getContactNote(contactId: string, noteId: string): Promise<GHLApiResponse<GHLNote>> {
|
|
try {
|
|
const response: AxiosResponse<{ note: GHLNote }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}/notes/${noteId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.note);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a note for a contact
|
|
* PUT /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async updateContactNote(contactId: string, noteId: string, updates: Partial<GHLNote>): Promise<GHLApiResponse<GHLNote>> {
|
|
try {
|
|
const response: AxiosResponse<{ note: GHLNote }> = await this.axiosInstance.put(
|
|
`/contacts/${contactId}/notes/${noteId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data.note);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a note for a contact
|
|
* DELETE /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async deleteContactNote(contactId: string, noteId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/notes/${noteId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upsert contact (create or update based on email/phone)
|
|
* POST /contacts/upsert
|
|
*/
|
|
async upsertContact(contactData: Partial<GHLCreateContactRequest>): Promise<GHLApiResponse<GHLUpsertContactResponse>> {
|
|
try {
|
|
const payload = {
|
|
...contactData,
|
|
locationId: contactData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpsertContactResponse> = await this.axiosInstance.post(
|
|
'/contacts/upsert',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get contacts by business ID
|
|
* GET /contacts/business/{businessId}
|
|
*/
|
|
async getContactsByBusiness(businessId: string, params: { limit?: number; skip?: number; query?: string } = {}): Promise<GHLApiResponse<GHLSearchContactsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
limit: params.limit || 25,
|
|
skip: params.skip || 0,
|
|
...(params.query && { query: params.query })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLSearchContactsResponse> = await this.axiosInstance.get(
|
|
`/contacts/business/${businessId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get contact appointments
|
|
* GET /contacts/{contactId}/appointments
|
|
*/
|
|
async getContactAppointments(contactId: string): Promise<GHLApiResponse<GHLAppointment[]>> {
|
|
try {
|
|
const response: AxiosResponse<{ events: GHLAppointment[] }> = await this.axiosInstance.get(
|
|
`/contacts/${contactId}/appointments`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.events);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk update contact tags
|
|
* POST /contacts/tags/bulk
|
|
*/
|
|
async bulkUpdateContactTags(contactIds: string[], tags: string[], operation: 'add' | 'remove', removeAllTags?: boolean): Promise<GHLApiResponse<GHLBulkTagsResponse>> {
|
|
try {
|
|
const payload = {
|
|
ids: contactIds,
|
|
tags,
|
|
operation,
|
|
...(removeAllTags !== undefined && { removeAllTags })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBulkTagsResponse> = await this.axiosInstance.post(
|
|
'/contacts/tags/bulk',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk update contact business
|
|
* POST /contacts/business/bulk
|
|
*/
|
|
async bulkUpdateContactBusiness(contactIds: string[], businessId?: string): Promise<GHLApiResponse<GHLBulkBusinessResponse>> {
|
|
try {
|
|
const payload = {
|
|
ids: contactIds,
|
|
businessId: businessId || null
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBulkBusinessResponse> = await this.axiosInstance.post(
|
|
'/contacts/business/bulk',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add contact followers
|
|
* POST /contacts/{contactId}/followers
|
|
*/
|
|
async addContactFollowers(contactId: string, followers: string[]): Promise<GHLApiResponse<GHLFollowersResponse>> {
|
|
try {
|
|
const payload = { followers };
|
|
|
|
const response: AxiosResponse<GHLFollowersResponse> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/followers`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove contact followers
|
|
* DELETE /contacts/{contactId}/followers
|
|
*/
|
|
async removeContactFollowers(contactId: string, followers: string[]): Promise<GHLApiResponse<GHLFollowersResponse>> {
|
|
try {
|
|
const payload = { followers };
|
|
|
|
const response: AxiosResponse<GHLFollowersResponse> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/followers`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add contact to campaign
|
|
* POST /contacts/{contactId}/campaigns/{campaignId}
|
|
*/
|
|
async addContactToCampaign(contactId: string, campaignId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/campaigns/${campaignId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove contact from campaign
|
|
* DELETE /contacts/{contactId}/campaigns/{campaignId}
|
|
*/
|
|
async removeContactFromCampaign(contactId: string, campaignId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/campaigns/${campaignId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove contact from all campaigns
|
|
* DELETE /contacts/{contactId}/campaigns
|
|
*/
|
|
async removeContactFromAllCampaigns(contactId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/campaigns`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add contact to workflow
|
|
* POST /contacts/{contactId}/workflow/{workflowId}
|
|
*/
|
|
async addContactToWorkflow(contactId: string, workflowId: string, eventStartTime?: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const payload = eventStartTime ? { eventStartTime } : {};
|
|
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.post(
|
|
`/contacts/${contactId}/workflow/${workflowId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove contact from workflow
|
|
* DELETE /contacts/{contactId}/workflow/{workflowId}
|
|
*/
|
|
async removeContactFromWorkflow(contactId: string, workflowId: string, eventStartTime?: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const payload = eventStartTime ? { eventStartTime } : {};
|
|
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/contacts/${contactId}/workflow/${workflowId}`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* UTILITY METHODS
|
|
*/
|
|
|
|
/**
|
|
* Test API connection and authentication
|
|
*/
|
|
async testConnection(): Promise<GHLApiResponse<{ status: string; locationId: string }>> {
|
|
try {
|
|
// Test with a simple GET request to check API connectivity
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get('/locations/' + this.config.locationId);
|
|
|
|
return this.wrapResponse({
|
|
status: 'connected',
|
|
locationId: this.config.locationId
|
|
});
|
|
} catch (error) {
|
|
throw new Error(`GHL API connection test failed: ${error}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update access token
|
|
*/
|
|
updateAccessToken(newToken: string): void {
|
|
this.config.accessToken = newToken;
|
|
this.axiosInstance.defaults.headers['Authorization'] = `Bearer ${newToken}`;
|
|
process.stderr.write('[GHL API] Access token updated\n');
|
|
}
|
|
|
|
/**
|
|
* Get current configuration
|
|
*/
|
|
getConfig(): Readonly<GHLConfig> {
|
|
return { ...this.config };
|
|
}
|
|
|
|
/**
|
|
* Generic request method for new endpoints
|
|
* Used by new tool modules that don't have specific client methods yet
|
|
*/
|
|
async makeRequest<T = any>(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', path: string, body?: Record<string, unknown>): Promise<GHLApiResponse<T>> {
|
|
try {
|
|
let response;
|
|
switch (method) {
|
|
case 'GET':
|
|
response = await this.axiosInstance.get(path);
|
|
break;
|
|
case 'POST':
|
|
response = await this.axiosInstance.post(path, body);
|
|
break;
|
|
case 'PUT':
|
|
response = await this.axiosInstance.put(path, body);
|
|
break;
|
|
case 'PATCH':
|
|
response = await this.axiosInstance.patch(path, body);
|
|
break;
|
|
case 'DELETE':
|
|
response = await this.axiosInstance.delete(path);
|
|
break;
|
|
}
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* OPPORTUNITIES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Search opportunities with advanced filters
|
|
* GET /opportunities/search
|
|
*/
|
|
async searchOpportunities(searchParams: GHLSearchOpportunitiesRequest): Promise<GHLApiResponse<GHLSearchOpportunitiesResponse>> {
|
|
try {
|
|
// Build query parameters with exact API naming (underscores)
|
|
const params: any = {
|
|
location_id: searchParams.location_id || this.config.locationId
|
|
};
|
|
|
|
// Add optional search parameters only if they have values
|
|
if (searchParams.q && searchParams.q.trim()) {
|
|
params.q = searchParams.q.trim();
|
|
}
|
|
|
|
if (searchParams.pipeline_id) {
|
|
params.pipeline_id = searchParams.pipeline_id;
|
|
}
|
|
|
|
if (searchParams.pipeline_stage_id) {
|
|
params.pipeline_stage_id = searchParams.pipeline_stage_id;
|
|
}
|
|
|
|
if (searchParams.contact_id) {
|
|
params.contact_id = searchParams.contact_id;
|
|
}
|
|
|
|
if (searchParams.status) {
|
|
params.status = searchParams.status;
|
|
}
|
|
|
|
if (searchParams.assigned_to) {
|
|
params.assigned_to = searchParams.assigned_to;
|
|
}
|
|
|
|
if (searchParams.campaignId) {
|
|
params.campaignId = searchParams.campaignId;
|
|
}
|
|
|
|
if (searchParams.id) {
|
|
params.id = searchParams.id;
|
|
}
|
|
|
|
if (searchParams.order) {
|
|
params.order = searchParams.order;
|
|
}
|
|
|
|
if (searchParams.endDate) {
|
|
params.endDate = searchParams.endDate;
|
|
}
|
|
|
|
if (searchParams.startAfter) {
|
|
params.startAfter = searchParams.startAfter;
|
|
}
|
|
|
|
if (searchParams.startAfterId) {
|
|
params.startAfterId = searchParams.startAfterId;
|
|
}
|
|
|
|
if (searchParams.date) {
|
|
params.date = searchParams.date;
|
|
}
|
|
|
|
if (searchParams.country) {
|
|
params.country = searchParams.country;
|
|
}
|
|
|
|
if (searchParams.page) {
|
|
params.page = searchParams.page;
|
|
}
|
|
|
|
if (searchParams.limit) {
|
|
params.limit = searchParams.limit;
|
|
}
|
|
|
|
if (searchParams.getTasks !== undefined) {
|
|
params.getTasks = searchParams.getTasks;
|
|
}
|
|
|
|
if (searchParams.getNotes !== undefined) {
|
|
params.getNotes = searchParams.getNotes;
|
|
}
|
|
|
|
if (searchParams.getCalendarEvents !== undefined) {
|
|
params.getCalendarEvents = searchParams.getCalendarEvents;
|
|
}
|
|
|
|
process.stderr.write(`[GHL API] Search opportunities params: ${JSON.stringify(params, null, 2)}\n`);
|
|
|
|
const response: AxiosResponse<GHLSearchOpportunitiesResponse> = await this.axiosInstance.get(
|
|
'/opportunities/search',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
const axiosError = error as AxiosError<GHLErrorResponse>;
|
|
process.stderr.write(`[GHL API] Search opportunities error: ${JSON.stringify({
|
|
status: axiosError.response?.status,
|
|
statusText: axiosError.response?.statusText,
|
|
data: axiosError.response?.data,
|
|
message: axiosError.message
|
|
}, null, 2)}\n`);
|
|
|
|
throw this.handleApiError(axiosError);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all pipelines for a location
|
|
* GET /opportunities/pipelines
|
|
*/
|
|
async getPipelines(locationId?: string): Promise<GHLApiResponse<GHLGetPipelinesResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetPipelinesResponse> = await this.axiosInstance.get(
|
|
'/opportunities/pipelines',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get opportunity by ID
|
|
* GET /opportunities/{id}
|
|
*/
|
|
async getOpportunity(opportunityId: string): Promise<GHLApiResponse<GHLOpportunity>> {
|
|
try {
|
|
const response: AxiosResponse<{ opportunity: GHLOpportunity }> = await this.axiosInstance.get(
|
|
`/opportunities/${opportunityId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data.opportunity);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new opportunity
|
|
* POST /opportunities/
|
|
*/
|
|
async createOpportunity(opportunityData: GHLCreateOpportunityRequest): Promise<GHLApiResponse<GHLOpportunity>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...opportunityData,
|
|
locationId: opportunityData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ opportunity: GHLOpportunity }> = await this.axiosInstance.post(
|
|
'/opportunities/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data.opportunity);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update existing opportunity
|
|
* PUT /opportunities/{id}
|
|
*/
|
|
async updateOpportunity(opportunityId: string, updates: GHLUpdateOpportunityRequest): Promise<GHLApiResponse<GHLOpportunity>> {
|
|
try {
|
|
const response: AxiosResponse<{ opportunity: GHLOpportunity }> = await this.axiosInstance.put(
|
|
`/opportunities/${opportunityId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data.opportunity);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update opportunity status
|
|
* PUT /opportunities/{id}/status
|
|
*/
|
|
async updateOpportunityStatus(opportunityId: string, status: GHLOpportunityStatus): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const payload: GHLUpdateOpportunityStatusRequest = { status };
|
|
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.put(
|
|
`/opportunities/${opportunityId}/status`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upsert opportunity (create or update)
|
|
* POST /opportunities/upsert
|
|
*/
|
|
async upsertOpportunity(opportunityData: GHLUpsertOpportunityRequest): Promise<GHLApiResponse<GHLUpsertOpportunityResponse>> {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...opportunityData,
|
|
locationId: opportunityData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpsertOpportunityResponse> = await this.axiosInstance.post(
|
|
'/opportunities/upsert',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete opportunity
|
|
* DELETE /opportunities/{id}
|
|
*/
|
|
async deleteOpportunity(opportunityId: string): Promise<GHLApiResponse<{ succeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeded: boolean }> = await this.axiosInstance.delete(
|
|
`/opportunities/${opportunityId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add followers to opportunity
|
|
* POST /opportunities/{id}/followers
|
|
*/
|
|
async addOpportunityFollowers(opportunityId: string, followers: string[]): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const payload = { followers };
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/opportunities/${opportunityId}/followers`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove followers from opportunity
|
|
* DELETE /opportunities/{id}/followers
|
|
*/
|
|
async removeOpportunityFollowers(opportunityId: string, followers: string[]): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const payload = { followers };
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/opportunities/${opportunityId}/followers`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* CALENDAR & APPOINTMENTS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get all calendar groups in a location
|
|
* GET /calendars/groups
|
|
*/
|
|
async getCalendarGroups(locationId?: string): Promise<GHLApiResponse<GHLGetCalendarGroupsResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetCalendarGroupsResponse> = await this.axiosInstance.get(
|
|
'/calendars/groups',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new calendar group
|
|
* POST /calendars/groups
|
|
*/
|
|
async createCalendarGroup(groupData: GHLCreateCalendarGroupRequest): Promise<GHLApiResponse<{ group: GHLCalendarGroup }>> {
|
|
try {
|
|
const payload = {
|
|
...groupData,
|
|
locationId: groupData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ group: GHLCalendarGroup }> = await this.axiosInstance.post(
|
|
'/calendars/groups',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all calendars in a location
|
|
* GET /calendars/
|
|
*/
|
|
async getCalendars(params?: { locationId?: string; groupId?: string; showDrafted?: boolean }): Promise<GHLApiResponse<GHLGetCalendarsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params?.locationId || this.config.locationId,
|
|
...(params?.groupId && { groupId: params.groupId }),
|
|
...(params?.showDrafted !== undefined && { showDrafted: params.showDrafted })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetCalendarsResponse> = await this.axiosInstance.get(
|
|
'/calendars/',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new calendar
|
|
* POST /calendars/
|
|
*/
|
|
async createCalendar(calendarData: GHLCreateCalendarRequest): Promise<GHLApiResponse<{ calendar: GHLCalendar }>> {
|
|
try {
|
|
const payload = {
|
|
...calendarData,
|
|
locationId: calendarData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<{ calendar: GHLCalendar }> = await this.axiosInstance.post(
|
|
'/calendars/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get calendar by ID
|
|
* GET /calendars/{calendarId}
|
|
*/
|
|
async getCalendar(calendarId: string): Promise<GHLApiResponse<{ calendar: GHLCalendar }>> {
|
|
try {
|
|
const response: AxiosResponse<{ calendar: GHLCalendar }> = await this.axiosInstance.get(
|
|
`/calendars/${calendarId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update calendar by ID
|
|
* PUT /calendars/{calendarId}
|
|
*/
|
|
async updateCalendar(calendarId: string, updates: GHLUpdateCalendarRequest): Promise<GHLApiResponse<{ calendar: GHLCalendar }>> {
|
|
try {
|
|
const response: AxiosResponse<{ calendar: GHLCalendar }> = await this.axiosInstance.put(
|
|
`/calendars/${calendarId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete calendar by ID
|
|
* DELETE /calendars/{calendarId}
|
|
*/
|
|
async deleteCalendar(calendarId: string): Promise<GHLApiResponse<{ success: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ success: boolean }> = await this.axiosInstance.delete(
|
|
`/calendars/${calendarId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get calendar events/appointments
|
|
* GET /calendars/events
|
|
*/
|
|
async getCalendarEvents(eventParams: GHLGetCalendarEventsRequest): Promise<GHLApiResponse<GHLGetCalendarEventsResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: eventParams.locationId || this.config.locationId,
|
|
startTime: eventParams.startTime,
|
|
endTime: eventParams.endTime,
|
|
...(eventParams.userId && { userId: eventParams.userId }),
|
|
...(eventParams.calendarId && { calendarId: eventParams.calendarId }),
|
|
...(eventParams.groupId && { groupId: eventParams.groupId })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetCalendarEventsResponse> = await this.axiosInstance.get(
|
|
'/calendars/events',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get blocked slots
|
|
* GET /calendars/blocked-slots
|
|
*/
|
|
async getBlockedSlots(eventParams: GHLGetCalendarEventsRequest): Promise<GHLApiResponse<GHLGetCalendarEventsResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: eventParams.locationId || this.config.locationId,
|
|
startTime: eventParams.startTime,
|
|
endTime: eventParams.endTime,
|
|
...(eventParams.userId && { userId: eventParams.userId }),
|
|
...(eventParams.calendarId && { calendarId: eventParams.calendarId }),
|
|
...(eventParams.groupId && { groupId: eventParams.groupId })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetCalendarEventsResponse> = await this.axiosInstance.get(
|
|
'/calendars/blocked-slots',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get free slots for a calendar
|
|
* GET /calendars/{calendarId}/free-slots
|
|
*/
|
|
async getFreeSlots(slotParams: GHLGetFreeSlotsRequest): Promise<GHLApiResponse<GHLGetFreeSlotsResponse>> {
|
|
try {
|
|
const params = {
|
|
startDate: slotParams.startDate,
|
|
endDate: slotParams.endDate,
|
|
...(slotParams.timezone && { timezone: slotParams.timezone }),
|
|
...(slotParams.userId && { userId: slotParams.userId }),
|
|
...(slotParams.userIds && { userIds: slotParams.userIds }),
|
|
...(slotParams.enableLookBusy !== undefined && { enableLookBusy: slotParams.enableLookBusy })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetFreeSlotsResponse> = await this.axiosInstance.get(
|
|
`/calendars/${slotParams.calendarId}/free-slots`,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new appointment
|
|
* POST /calendars/events/appointments
|
|
*/
|
|
async createAppointment(appointmentData: GHLCreateAppointmentRequest): Promise<GHLApiResponse<GHLCalendarEvent>> {
|
|
try {
|
|
const payload = {
|
|
...appointmentData,
|
|
locationId: appointmentData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCalendarEvent> = await this.axiosInstance.post(
|
|
'/calendars/events/appointments',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get appointment by ID
|
|
* GET /calendars/events/appointments/{eventId}
|
|
*/
|
|
async getAppointment(appointmentId: string): Promise<GHLApiResponse<{ event: GHLCalendarEvent }>> {
|
|
try {
|
|
const response: AxiosResponse<{ event: GHLCalendarEvent }> = await this.axiosInstance.get(
|
|
`/calendars/events/appointments/${appointmentId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update appointment by ID
|
|
* PUT /calendars/events/appointments/{eventId}
|
|
*/
|
|
async updateAppointment(appointmentId: string, updates: GHLUpdateAppointmentRequest): Promise<GHLApiResponse<GHLCalendarEvent>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarEvent> = await this.axiosInstance.put(
|
|
`/calendars/events/appointments/${appointmentId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete appointment by ID
|
|
* DELETE /calendars/events/appointments/{eventId}
|
|
*/
|
|
async deleteAppointment(appointmentId: string): Promise<GHLApiResponse<{ succeeded: boolean }>> {
|
|
try {
|
|
const response: AxiosResponse<{ succeeded: boolean }> = await this.axiosInstance.delete(
|
|
`/calendars/events/appointments/${appointmentId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Update block slot by ID
|
|
* PUT /calendars/events/block-slots/{eventId}
|
|
*/
|
|
async updateBlockSlot(blockSlotId: string, updates: GHLUpdateBlockSlotRequest): Promise<GHLApiResponse<GHLBlockSlotResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLBlockSlotResponse> = await this.axiosInstance.put(
|
|
`/calendars/events/block-slots/${blockSlotId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EMAIL API METHODS
|
|
*/
|
|
|
|
async getEmailCampaigns(params: MCPGetEmailCampaignsParams): Promise<GHLApiResponse<GHLEmailCampaignsResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLEmailCampaignsResponse> = await this.axiosInstance.get('/emails/schedule', {
|
|
params: {
|
|
locationId: this.config.locationId,
|
|
...params
|
|
}
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
async createEmailTemplate(params: MCPCreateEmailTemplateParams): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post('/emails/builder', {
|
|
locationId: this.config.locationId,
|
|
type: 'html',
|
|
...params
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
async getEmailTemplates(params: MCPGetEmailTemplatesParams): Promise<GHLApiResponse<GHLEmailTemplate[]>> {
|
|
try {
|
|
const response: AxiosResponse<GHLEmailTemplate[]> = await this.axiosInstance.get('/emails/builder', {
|
|
params: {
|
|
locationId: this.config.locationId,
|
|
...params
|
|
}
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
async updateEmailTemplate(params: MCPUpdateEmailTemplateParams): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const { templateId, ...data } = params;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post('/emails/builder/data', {
|
|
locationId: this.config.locationId,
|
|
templateId,
|
|
...data,
|
|
editorType: 'html'
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
async deleteEmailTemplate(params: MCPDeleteEmailTemplateParams): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const { templateId } = params;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(`/emails/builder/${this.config.locationId}/${templateId}`);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* LOCATION API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Search locations/sub-accounts
|
|
* GET /locations/search
|
|
*/
|
|
async searchLocations(params: {
|
|
companyId?: string;
|
|
skip?: number;
|
|
limit?: number;
|
|
order?: 'asc' | 'desc';
|
|
email?: string;
|
|
} = {}): Promise<GHLApiResponse<GHLLocationSearchResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
skip: params.skip || 0,
|
|
limit: params.limit || 10,
|
|
order: params.order || 'asc',
|
|
...(params.companyId && { companyId: params.companyId }),
|
|
...(params.email && { email: params.email })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLLocationSearchResponse> = await this.axiosInstance.get(
|
|
'/locations/search',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get location by ID
|
|
* GET /locations/{locationId}
|
|
*/
|
|
async getLocationById(locationId: string): Promise<GHLApiResponse<GHLLocationDetailsResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationDetailsResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new location/sub-account
|
|
* POST /locations/
|
|
*/
|
|
async createLocation(locationData: GHLCreateLocationRequest): Promise<GHLApiResponse<GHLLocationDetailed>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationDetailed> = await this.axiosInstance.post(
|
|
'/locations/',
|
|
locationData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update location/sub-account
|
|
* PUT /locations/{locationId}
|
|
*/
|
|
async updateLocation(locationId: string, updates: GHLUpdateLocationRequest): Promise<GHLApiResponse<GHLLocationDetailed>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationDetailed> = await this.axiosInstance.put(
|
|
`/locations/${locationId}`,
|
|
updates
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete location/sub-account
|
|
* DELETE /locations/{locationId}
|
|
*/
|
|
async deleteLocation(locationId: string, deleteTwilioAccount: boolean): Promise<GHLApiResponse<GHLLocationDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationDeleteResponse> = await this.axiosInstance.delete(
|
|
`/locations/${locationId}`,
|
|
{
|
|
params: { deleteTwilioAccount }
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* LOCATION TAGS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get location tags
|
|
* GET /locations/{locationId}/tags
|
|
*/
|
|
async getLocationTags(locationId: string): Promise<GHLApiResponse<GHLLocationTagsResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTagsResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/tags`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create location tag
|
|
* POST /locations/{locationId}/tags
|
|
*/
|
|
async createLocationTag(locationId: string, tagData: GHLLocationTagRequest): Promise<GHLApiResponse<GHLLocationTagResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTagResponse> = await this.axiosInstance.post(
|
|
`/locations/${locationId}/tags`,
|
|
tagData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get location tag by ID
|
|
* GET /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async getLocationTag(locationId: string, tagId: string): Promise<GHLApiResponse<GHLLocationTagResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTagResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/tags/${tagId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update location tag
|
|
* PUT /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async updateLocationTag(locationId: string, tagId: string, tagData: GHLLocationTagRequest): Promise<GHLApiResponse<GHLLocationTagResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTagResponse> = await this.axiosInstance.put(
|
|
`/locations/${locationId}/tags/${tagId}`,
|
|
tagData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete location tag
|
|
* DELETE /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async deleteLocationTag(locationId: string, tagId: string): Promise<GHLApiResponse<GHLLocationTagDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTagDeleteResponse> = await this.axiosInstance.delete(
|
|
`/locations/${locationId}/tags/${tagId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* LOCATION TASKS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Search location tasks
|
|
* POST /locations/{locationId}/tasks/search
|
|
*/
|
|
async searchLocationTasks(locationId: string, searchParams: GHLLocationTaskSearchRequest): Promise<GHLApiResponse<GHLLocationTaskSearchResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationTaskSearchResponse> = await this.axiosInstance.post(
|
|
`/locations/${locationId}/tasks/search`,
|
|
searchParams
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* CUSTOM FIELDS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get custom fields for location
|
|
* GET /locations/{locationId}/customFields
|
|
*/
|
|
async getLocationCustomFields(locationId: string, model?: 'contact' | 'opportunity' | 'all'): Promise<GHLApiResponse<GHLLocationCustomFieldsResponse>> {
|
|
try {
|
|
const params: any = {};
|
|
if (model) params.model = model;
|
|
|
|
const response: AxiosResponse<GHLLocationCustomFieldsResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/customFields`,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom field for location
|
|
* POST /locations/{locationId}/customFields
|
|
*/
|
|
async createLocationCustomField(locationId: string, fieldData: GHLCreateCustomFieldRequest): Promise<GHLApiResponse<GHLLocationCustomFieldResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomFieldResponse> = await this.axiosInstance.post(
|
|
`/locations/${locationId}/customFields`,
|
|
fieldData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get custom field by ID
|
|
* GET /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async getLocationCustomField(locationId: string, customFieldId: string): Promise<GHLApiResponse<GHLLocationCustomFieldResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomFieldResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/customFields/${customFieldId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update custom field
|
|
* PUT /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async updateLocationCustomField(locationId: string, customFieldId: string, fieldData: GHLUpdateCustomFieldRequest): Promise<GHLApiResponse<GHLLocationCustomFieldResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomFieldResponse> = await this.axiosInstance.put(
|
|
`/locations/${locationId}/customFields/${customFieldId}`,
|
|
fieldData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete custom field
|
|
* DELETE /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async deleteLocationCustomField(locationId: string, customFieldId: string): Promise<GHLApiResponse<GHLCustomFieldDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCustomFieldDeleteResponse> = await this.axiosInstance.delete(
|
|
`/locations/${locationId}/customFields/${customFieldId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upload file to custom fields
|
|
* POST /locations/{locationId}/customFields/upload
|
|
*/
|
|
async uploadLocationCustomFieldFile(locationId: string, uploadData: GHLFileUploadRequest): Promise<GHLApiResponse<GHLFileUploadResponse>> {
|
|
try {
|
|
// Note: This endpoint expects multipart/form-data but we'll handle it as JSON for now
|
|
// In a real implementation, you'd use FormData for file uploads
|
|
const response: AxiosResponse<GHLFileUploadResponse> = await this.axiosInstance.post(
|
|
`/locations/${locationId}/customFields/upload`,
|
|
uploadData,
|
|
{ headers: { 'Content-Type': 'multipart/form-data' } }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* CUSTOM VALUES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get custom values for location
|
|
* GET /locations/{locationId}/customValues
|
|
*/
|
|
async getLocationCustomValues(locationId: string): Promise<GHLApiResponse<GHLLocationCustomValuesResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomValuesResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/customValues`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom value for location
|
|
* POST /locations/{locationId}/customValues
|
|
*/
|
|
async createLocationCustomValue(locationId: string, valueData: GHLCustomValueRequest): Promise<GHLApiResponse<GHLLocationCustomValueResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomValueResponse> = await this.axiosInstance.post(
|
|
`/locations/${locationId}/customValues`,
|
|
valueData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get custom value by ID
|
|
* GET /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async getLocationCustomValue(locationId: string, customValueId: string): Promise<GHLApiResponse<GHLLocationCustomValueResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomValueResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/customValues/${customValueId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update custom value
|
|
* PUT /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async updateLocationCustomValue(locationId: string, customValueId: string, valueData: GHLCustomValueRequest): Promise<GHLApiResponse<GHLLocationCustomValueResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLocationCustomValueResponse> = await this.axiosInstance.put(
|
|
`/locations/${locationId}/customValues/${customValueId}`,
|
|
valueData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete custom value
|
|
* DELETE /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async deleteLocationCustomValue(locationId: string, customValueId: string): Promise<GHLApiResponse<GHLCustomValueDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCustomValueDeleteResponse> = await this.axiosInstance.delete(
|
|
`/locations/${locationId}/customValues/${customValueId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TEMPLATES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get location templates (SMS/Email)
|
|
* GET /locations/{locationId}/templates
|
|
*/
|
|
async getLocationTemplates(locationId: string, params: {
|
|
originId: string;
|
|
deleted?: boolean;
|
|
skip?: number;
|
|
limit?: number;
|
|
type?: 'sms' | 'email' | 'whatsapp';
|
|
}): Promise<GHLApiResponse<GHLLocationTemplatesResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
originId: params.originId,
|
|
deleted: params.deleted || false,
|
|
skip: params.skip || 0,
|
|
limit: params.limit || 25,
|
|
...(params.type && { type: params.type })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLLocationTemplatesResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/templates`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete location template
|
|
* DELETE /locations/{locationId}/templates/{id}
|
|
*/
|
|
async deleteLocationTemplate(locationId: string, templateId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/locations/${locationId}/templates/${templateId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TIMEZONES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get available timezones
|
|
* GET /locations/{locationId}/timezones
|
|
*/
|
|
async getTimezones(locationId?: string): Promise<GHLApiResponse<string[]>> {
|
|
try {
|
|
const endpoint = locationId ? `/locations/${locationId}/timezones` : '/locations/timezones';
|
|
const response: AxiosResponse<string[]> = await this.axiosInstance.get(endpoint);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* EMAIL ISV (VERIFICATION) API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Verify email address or contact
|
|
* POST /email/verify
|
|
*/
|
|
async verifyEmail(locationId: string, verificationData: GHLEmailVerificationRequest): Promise<GHLApiResponse<GHLEmailVerificationResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLEmailVerificationResponse> = await this.axiosInstance.post(
|
|
'/email/verify',
|
|
verificationData,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ADDITIONAL CONVERSATION/MESSAGE API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get email message by ID
|
|
* GET /conversations/messages/email/{id}
|
|
*/
|
|
async getEmailMessage(emailMessageId: string): Promise<GHLApiResponse<GHLEmailMessage>> {
|
|
try {
|
|
const response: AxiosResponse<GHLEmailMessage> = await this.axiosInstance.get(
|
|
`/conversations/messages/email/${emailMessageId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancel scheduled email message
|
|
* DELETE /conversations/messages/email/{emailMessageId}/schedule
|
|
*/
|
|
async cancelScheduledEmail(emailMessageId: string): Promise<GHLApiResponse<GHLCancelScheduledResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCancelScheduledResponse> = await this.axiosInstance.delete(
|
|
`/conversations/messages/email/${emailMessageId}/schedule`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add inbound message manually
|
|
* POST /conversations/messages/inbound
|
|
*/
|
|
async addInboundMessage(messageData: GHLProcessInboundMessageRequest): Promise<GHLApiResponse<GHLProcessMessageResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLProcessMessageResponse> = await this.axiosInstance.post(
|
|
'/conversations/messages/inbound',
|
|
messageData,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add outbound call manually
|
|
* POST /conversations/messages/outbound
|
|
*/
|
|
async addOutboundCall(messageData: GHLProcessOutboundMessageRequest): Promise<GHLApiResponse<GHLProcessMessageResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLProcessMessageResponse> = await this.axiosInstance.post(
|
|
'/conversations/messages/outbound',
|
|
messageData,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancel scheduled message
|
|
* DELETE /conversations/messages/{messageId}/schedule
|
|
*/
|
|
async cancelScheduledMessage(messageId: string): Promise<GHLApiResponse<GHLCancelScheduledResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCancelScheduledResponse> = await this.axiosInstance.delete(
|
|
`/conversations/messages/${messageId}/schedule`,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upload file attachments for messages
|
|
* POST /conversations/messages/upload
|
|
*/
|
|
async uploadMessageAttachments(uploadData: GHLUploadFilesRequest): Promise<GHLApiResponse<GHLUploadFilesResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLUploadFilesResponse> = await this.axiosInstance.post(
|
|
'/conversations/messages/upload',
|
|
uploadData,
|
|
{
|
|
headers: {
|
|
...this.getConversationHeaders(),
|
|
'Content-Type': 'multipart/form-data'
|
|
}
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update message status
|
|
* PUT /conversations/messages/{messageId}/status
|
|
*/
|
|
async updateMessageStatus(messageId: string, statusData: GHLUpdateMessageStatusRequest): Promise<GHLApiResponse<GHLSendMessageResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLSendMessageResponse> = await this.axiosInstance.put(
|
|
`/conversations/messages/${messageId}/status`,
|
|
statusData,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get message recording
|
|
* GET /conversations/messages/{messageId}/locations/{locationId}/recording
|
|
*/
|
|
async getMessageRecording(messageId: string, locationId?: string): Promise<GHLApiResponse<GHLMessageRecordingResponse>> {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response: AxiosResponse<ArrayBuffer> = await this.axiosInstance.get(
|
|
`/conversations/messages/${messageId}/locations/${locId}/recording`,
|
|
{
|
|
headers: this.getConversationHeaders(),
|
|
responseType: 'arraybuffer'
|
|
}
|
|
);
|
|
|
|
const recordingResponse: GHLMessageRecordingResponse = {
|
|
audioData: response.data,
|
|
contentType: response.headers['content-type'] || 'audio/x-wav',
|
|
contentDisposition: response.headers['content-disposition'] || 'attachment; filename=audio.wav'
|
|
};
|
|
|
|
return this.wrapResponse(recordingResponse);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get message transcription
|
|
* GET /conversations/locations/{locationId}/messages/{messageId}/transcription
|
|
*/
|
|
async getMessageTranscription(messageId: string, locationId?: string): Promise<GHLApiResponse<GHLMessageTranscriptionResponse>> {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response: AxiosResponse<GHLMessageTranscription[]> = await this.axiosInstance.get(
|
|
`/conversations/locations/${locId}/messages/${messageId}/transcription`,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse({ transcriptions: response.data });
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Download message transcription
|
|
* GET /conversations/locations/{locationId}/messages/{messageId}/transcription/download
|
|
*/
|
|
async downloadMessageTranscription(messageId: string, locationId?: string): Promise<GHLApiResponse<string>> {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response: AxiosResponse<string> = await this.axiosInstance.get(
|
|
`/conversations/locations/${locId}/messages/${messageId}/transcription/download`,
|
|
{
|
|
headers: this.getConversationHeaders(),
|
|
responseType: 'text'
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Live chat typing indicator
|
|
* POST /conversations/providers/live-chat/typing
|
|
*/
|
|
async liveChatTyping(typingData: GHLLiveChatTypingRequest): Promise<GHLApiResponse<GHLLiveChatTypingResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLLiveChatTypingResponse> = await this.axiosInstance.post(
|
|
'/conversations/providers/live-chat/typing',
|
|
typingData,
|
|
{ headers: this.getConversationHeaders() }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// SOCIAL MEDIA POSTING API METHODS
|
|
// ============================================================================
|
|
|
|
// ===== POST MANAGEMENT =====
|
|
|
|
/**
|
|
* Search/List Social Media Posts
|
|
*/
|
|
async searchSocialPosts(searchData: GHLSearchPostsRequest): Promise<GHLApiResponse<GHLSearchPostsResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<GHLSearchPostsResponse> = await this.axiosInstance.post(
|
|
`/social-media-posting/${locationId}/posts/list`,
|
|
searchData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create Social Media Post
|
|
*/
|
|
async createSocialPost(postData: GHLCreatePostRequest): Promise<GHLApiResponse<GHLCreatePostResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<GHLCreatePostResponse> = await this.axiosInstance.post(
|
|
`/social-media-posting/${locationId}/posts`,
|
|
postData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Social Media Post by ID
|
|
*/
|
|
async getSocialPost(postId: string): Promise<GHLApiResponse<GHLGetPostResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<GHLGetPostResponse> = await this.axiosInstance.get(
|
|
`/social-media-posting/${locationId}/posts/${postId}`
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update Social Media Post
|
|
*/
|
|
async updateSocialPost(postId: string, updateData: GHLUpdatePostRequest): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.put(
|
|
`/social-media-posting/${locationId}/posts/${postId}`,
|
|
updateData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete Social Media Post
|
|
*/
|
|
async deleteSocialPost(postId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/social-media-posting/${locationId}/posts/${postId}`
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk Delete Social Media Posts
|
|
*/
|
|
async bulkDeleteSocialPosts(deleteData: GHLBulkDeletePostsRequest): Promise<GHLApiResponse<GHLBulkDeleteResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<GHLBulkDeleteResponse> = await this.axiosInstance.post(
|
|
`/social-media-posting/${locationId}/posts/bulk-delete`,
|
|
deleteData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ===== ACCOUNT MANAGEMENT =====
|
|
|
|
/**
|
|
* Get Social Media Accounts and Groups
|
|
*/
|
|
async getSocialAccounts(): Promise<GHLApiResponse<GHLGetAccountsResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<GHLGetAccountsResponse> = await this.axiosInstance.get(
|
|
`/social-media-posting/${locationId}/accounts`
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete Social Media Account
|
|
*/
|
|
async deleteSocialAccount(accountId: string, companyId?: string, userId?: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params: any = {};
|
|
if (companyId) params.companyId = companyId;
|
|
if (userId) params.userId = userId;
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/social-media-posting/${locationId}/accounts/${accountId}`,
|
|
{ params }
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ===== CSV OPERATIONS =====
|
|
|
|
/**
|
|
* Upload CSV for Social Media Posts
|
|
*/
|
|
async uploadSocialCSV(csvData: GHLUploadCSVRequest): Promise<GHLApiResponse<GHLUploadCSVResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
// Note: This would typically use FormData for file upload
|
|
const response: AxiosResponse<GHLUploadCSVResponse> = await this.axiosInstance.post(
|
|
`/social-media-posting/${locationId}/csv`,
|
|
csvData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get CSV Upload Status
|
|
*/
|
|
async getSocialCSVUploadStatus(skip?: number, limit?: number, includeUsers?: boolean, userId?: string): Promise<GHLApiResponse<GHLGetUploadStatusResponse>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params: any = {};
|
|
if (skip !== undefined) params.skip = skip.toString();
|
|
if (limit !== undefined) params.limit = limit.toString();
|
|
if (includeUsers !== undefined) params.includeUsers = includeUsers.toString();
|
|
if (userId) params.userId = userId;
|
|
|
|
const response: AxiosResponse<GHLGetUploadStatusResponse> = await this.axiosInstance.get(
|
|
`/social-media-posting/${locationId}/csv`,
|
|
{ params }
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set Accounts for CSV Import
|
|
*/
|
|
async setSocialCSVAccounts(accountsData: GHLSetAccountsRequest): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/social-media-posting/${locationId}/set-accounts`,
|
|
accountsData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get CSV Posts
|
|
*/
|
|
async getSocialCSVPosts(csvId: string, skip?: number, limit?: number): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params: any = {};
|
|
if (skip !== undefined) params.skip = skip.toString();
|
|
if (limit !== undefined) params.limit = limit.toString();
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/social-media-posting/${locationId}/csv/${csvId}`,
|
|
{ params }
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Start CSV Finalization
|
|
*/
|
|
async finalizeSocialCSV(csvId: string, finalizeData: GHLCSVFinalizeRequest): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.patch(
|
|
`/social-media-posting/${locationId}/csv/${csvId}`,
|
|
finalizeData
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete CSV Import
|
|
*/
|
|
async deleteSocialCSV(csvId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/social-media-posting/${locationId}/csv/${csvId}`
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete CSV Post
|
|
*/
|
|
async deleteSocialCSVPost(csvId: string, postId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/social-media-posting/${locationId}/csv/${csvId}/post/${postId}`
|
|
);
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ===== CATEGORIES & TAGS =====
|
|
|
|
/**
|
|
* Get Social Media Categories
|
|
*/
|
|
async getSocialCategories(searchText?: string, limit?: number, skip?: number): Promise<GHLApiResponse<GHLGetCategoriesResponse>> {
|
|
// TODO: Implement this method properly
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
// TODO: Implement remaining social media API methods
|
|
async getSocialCategory(categoryId: string): Promise<GHLApiResponse<GHLGetCategoryResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getSocialTags(searchText?: string, limit?: number, skip?: number): Promise<GHLApiResponse<GHLGetTagsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getSocialTagsByIds(tagData: GHLGetTagsByIdsRequest): Promise<GHLApiResponse<GHLGetTagsByIdsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async startSocialOAuth(platform: GHLSocialPlatform, userId: string, page?: string, reconnect?: boolean): Promise<GHLApiResponse<GHLOAuthStartResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getGoogleBusinessLocations(accountId: string): Promise<GHLApiResponse<GHLGetGoogleLocationsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async setGoogleBusinessLocations(accountId: string, locationData: GHLAttachGMBLocationRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getFacebookPages(accountId: string): Promise<GHLApiResponse<GHLGetFacebookPagesResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async attachFacebookPages(accountId: string, pageData: GHLAttachFBAccountRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getInstagramAccounts(accountId: string): Promise<GHLApiResponse<GHLGetInstagramAccountsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async attachInstagramAccounts(accountId: string, accountData: GHLAttachIGAccountRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getLinkedInAccounts(accountId: string): Promise<GHLApiResponse<GHLGetLinkedInAccountsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async attachLinkedInAccounts(accountId: string, accountData: GHLAttachLinkedInAccountRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getTwitterProfile(accountId: string): Promise<GHLApiResponse<GHLGetTwitterAccountsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async attachTwitterProfile(accountId: string, profileData: GHLAttachTwitterAccountRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getTikTokProfile(accountId: string): Promise<GHLApiResponse<GHLGetTikTokAccountsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async attachTikTokProfile(accountId: string, profileData: GHLAttachTikTokAccountRequest): Promise<GHLApiResponse<GHLSocialAccount>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
async getTikTokBusinessProfile(accountId: string): Promise<GHLApiResponse<GHLGetTikTokAccountsResponse>> {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
|
|
// ===== MISSING CALENDAR GROUPS MANAGEMENT METHODS =====
|
|
|
|
/**
|
|
* Validate calendar group slug
|
|
* GET /calendars/groups/slug/validate
|
|
*/
|
|
async validateCalendarGroupSlug(slug: string, locationId?: string): Promise<GHLApiResponse<GHLValidateGroupSlugResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId,
|
|
slug
|
|
};
|
|
|
|
const response: AxiosResponse<GHLValidateGroupSlugResponse> = await this.axiosInstance.get(
|
|
'/calendars/groups/slug/validate',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update calendar group by ID
|
|
* PUT /calendars/groups/{groupId}
|
|
*/
|
|
async updateCalendarGroup(groupId: string, updateData: GHLUpdateCalendarGroupRequest): Promise<GHLApiResponse<GHLGroupSuccessResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLGroupSuccessResponse> = await this.axiosInstance.put(
|
|
`/calendars/groups/${groupId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete calendar group by ID
|
|
* DELETE /calendars/groups/{groupId}
|
|
*/
|
|
async deleteCalendarGroup(groupId: string): Promise<GHLApiResponse<GHLGroupSuccessResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLGroupSuccessResponse> = await this.axiosInstance.delete(
|
|
`/calendars/groups/${groupId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable calendar group
|
|
* POST /calendars/groups/{groupId}/status
|
|
*/
|
|
async disableCalendarGroup(groupId: string, isActive: boolean): Promise<GHLApiResponse<GHLGroupSuccessResponse>> {
|
|
try {
|
|
const payload: GHLGroupStatusUpdateRequest = { isActive };
|
|
|
|
const response: AxiosResponse<GHLGroupSuccessResponse> = await this.axiosInstance.post(
|
|
`/calendars/groups/${groupId}/status`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== APPOINTMENT NOTES METHODS =====
|
|
|
|
/**
|
|
* Get appointment notes
|
|
* GET /calendars/events/appointments/{appointmentId}/notes
|
|
*/
|
|
async getAppointmentNotes(appointmentId: string, limit = 10, offset = 0): Promise<GHLApiResponse<GHLGetAppointmentNotesResponse>> {
|
|
try {
|
|
const params = { limit, offset };
|
|
|
|
const response: AxiosResponse<GHLGetAppointmentNotesResponse> = await this.axiosInstance.get(
|
|
`/calendars/events/appointments/${appointmentId}/notes`,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create appointment note
|
|
* POST /calendars/events/appointments/{appointmentId}/notes
|
|
*/
|
|
async createAppointmentNote(appointmentId: string, noteData: GHLCreateAppointmentNoteRequest): Promise<GHLApiResponse<GHLAppointmentNoteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLAppointmentNoteResponse> = await this.axiosInstance.post(
|
|
`/calendars/events/appointments/${appointmentId}/notes`,
|
|
noteData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update appointment note
|
|
* PUT /calendars/events/appointments/{appointmentId}/notes/{noteId}
|
|
*/
|
|
async updateAppointmentNote(appointmentId: string, noteId: string, updateData: GHLUpdateAppointmentNoteRequest): Promise<GHLApiResponse<GHLAppointmentNoteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLAppointmentNoteResponse> = await this.axiosInstance.put(
|
|
`/calendars/events/appointments/${appointmentId}/notes/${noteId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete appointment note
|
|
* DELETE /calendars/events/appointments/{appointmentId}/notes/{noteId}
|
|
*/
|
|
async deleteAppointmentNote(appointmentId: string, noteId: string): Promise<GHLApiResponse<GHLDeleteAppointmentNoteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLDeleteAppointmentNoteResponse> = await this.axiosInstance.delete(
|
|
`/calendars/events/appointments/${appointmentId}/notes/${noteId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== CALENDAR RESOURCES METHODS =====
|
|
|
|
/**
|
|
* Get calendar resources
|
|
* GET /calendars/resources/{resourceType}
|
|
*/
|
|
async getCalendarResources(resourceType: 'equipments' | 'rooms', limit = 20, skip = 0, locationId?: string): Promise<GHLApiResponse<GHLCalendarResource[]>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId,
|
|
limit,
|
|
skip
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCalendarResource[]> = await this.axiosInstance.get(
|
|
`/calendars/resources/${resourceType}`,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create calendar resource
|
|
* POST /calendars/resources/{resourceType}
|
|
*/
|
|
async createCalendarResource(resourceType: 'equipments' | 'rooms', resourceData: GHLCreateCalendarResourceRequest): Promise<GHLApiResponse<GHLCalendarResourceResponse>> {
|
|
try {
|
|
const payload = {
|
|
...resourceData,
|
|
locationId: resourceData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCalendarResourceResponse> = await this.axiosInstance.post(
|
|
`/calendars/resources/${resourceType}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get calendar resource by ID
|
|
* GET /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async getCalendarResource(resourceType: 'equipments' | 'rooms', resourceId: string): Promise<GHLApiResponse<GHLCalendarResourceByIdResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarResourceByIdResponse> = await this.axiosInstance.get(
|
|
`/calendars/resources/${resourceType}/${resourceId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update calendar resource
|
|
* PUT /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async updateCalendarResource(resourceType: 'equipments' | 'rooms', resourceId: string, updateData: GHLUpdateCalendarResourceRequest): Promise<GHLApiResponse<GHLCalendarResourceResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarResourceResponse> = await this.axiosInstance.put(
|
|
`/calendars/resources/${resourceType}/${resourceId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete calendar resource
|
|
* DELETE /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async deleteCalendarResource(resourceType: 'equipments' | 'rooms', resourceId: string): Promise<GHLApiResponse<GHLResourceDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLResourceDeleteResponse> = await this.axiosInstance.delete(
|
|
`/calendars/resources/${resourceType}/${resourceId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== CALENDAR NOTIFICATIONS METHODS =====
|
|
|
|
/**
|
|
* Get calendar notifications
|
|
* GET /calendars/{calendarId}/notifications
|
|
*/
|
|
async getCalendarNotifications(calendarId: string, queryParams?: GHLGetCalendarNotificationsRequest): Promise<GHLApiResponse<GHLCalendarNotification[]>> {
|
|
try {
|
|
const params = {
|
|
...queryParams
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCalendarNotification[]> = await this.axiosInstance.get(
|
|
`/calendars/${calendarId}/notifications`,
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create calendar notifications
|
|
* POST /calendars/{calendarId}/notifications
|
|
*/
|
|
async createCalendarNotifications(calendarId: string, notifications: GHLCreateCalendarNotificationRequest[]): Promise<GHLApiResponse<GHLCalendarNotification[]>> {
|
|
try {
|
|
const payload = { notifications };
|
|
|
|
const response: AxiosResponse<GHLCalendarNotification[]> = await this.axiosInstance.post(
|
|
`/calendars/${calendarId}/notifications`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get calendar notification by ID
|
|
* GET /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async getCalendarNotification(calendarId: string, notificationId: string): Promise<GHLApiResponse<GHLCalendarNotification>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarNotification> = await this.axiosInstance.get(
|
|
`/calendars/${calendarId}/notifications/${notificationId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update calendar notification
|
|
* PUT /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async updateCalendarNotification(calendarId: string, notificationId: string, updateData: GHLUpdateCalendarNotificationRequest): Promise<GHLApiResponse<GHLCalendarNotification>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarNotification> = await this.axiosInstance.put(
|
|
`/calendars/${calendarId}/notifications/${notificationId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete calendar notification
|
|
* DELETE /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async deleteCalendarNotification(calendarId: string, notificationId: string): Promise<GHLApiResponse<GHLCalendarNotificationDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCalendarNotificationDeleteResponse> = await this.axiosInstance.delete(
|
|
`/calendars/${calendarId}/notifications/${notificationId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get blocked slots by location
|
|
* GET /calendars/blocked-slots
|
|
*/
|
|
async getBlockedSlotsByLocation(slotParams: GHLGetBlockedSlotsRequest): Promise<GHLApiResponse<GHLGetCalendarEventsResponse>> {
|
|
try {
|
|
const params = new URLSearchParams({
|
|
locationId: slotParams.locationId,
|
|
startTime: slotParams.startTime,
|
|
endTime: slotParams.endTime,
|
|
...(slotParams.userId && { userId: slotParams.userId }),
|
|
...(slotParams.calendarId && { calendarId: slotParams.calendarId }),
|
|
...(slotParams.groupId && { groupId: slotParams.groupId })
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetCalendarEventsResponse> = await this.axiosInstance.get(
|
|
`/calendars/blocked-slots?${params}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new block slot
|
|
* POST /calendars/blocked-slots
|
|
*/
|
|
async createBlockSlot(blockSlotData: GHLCreateBlockSlotRequest): Promise<GHLApiResponse<GHLBlockSlotResponse>> {
|
|
try {
|
|
const payload = {
|
|
...blockSlotData,
|
|
locationId: blockSlotData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBlockSlotResponse> = await this.axiosInstance.post(
|
|
'/calendars/blocked-slots',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== MEDIA LIBRARY API METHODS =====
|
|
|
|
/**
|
|
* Get list of files and folders from media library
|
|
* GET /medias/files
|
|
*/
|
|
async getMediaFiles(params: GHLGetMediaFilesRequest): Promise<GHLApiResponse<GHLGetMediaFilesResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
sortBy: params.sortBy,
|
|
sortOrder: params.sortOrder,
|
|
altType: params.altType,
|
|
altId: params.altId,
|
|
...(params.offset !== undefined && { offset: params.offset.toString() }),
|
|
...(params.limit !== undefined && { limit: params.limit.toString() }),
|
|
...(params.type && { type: params.type }),
|
|
...(params.query && { query: params.query }),
|
|
...(params.parentId && { parentId: params.parentId })
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetMediaFilesResponse> = await this.axiosInstance.get(
|
|
`/medias/files?${queryParams}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upload file to media library
|
|
* POST /medias/upload-file
|
|
*/
|
|
async uploadMediaFile(uploadData: GHLUploadMediaFileRequest): Promise<GHLApiResponse<GHLUploadMediaFileResponse>> {
|
|
try {
|
|
const formData = new FormData();
|
|
|
|
// Handle file upload (either direct file or hosted file URL)
|
|
if (uploadData.hosted && uploadData.fileUrl) {
|
|
formData.append('hosted', 'true');
|
|
formData.append('fileUrl', uploadData.fileUrl);
|
|
} else if (uploadData.file) {
|
|
formData.append('hosted', 'false');
|
|
formData.append('file', uploadData.file);
|
|
} else {
|
|
throw new Error('Either file or fileUrl (with hosted=true) must be provided');
|
|
}
|
|
|
|
// Add optional fields
|
|
if (uploadData.name) {
|
|
formData.append('name', uploadData.name);
|
|
}
|
|
if (uploadData.parentId) {
|
|
formData.append('parentId', uploadData.parentId);
|
|
}
|
|
|
|
const response: AxiosResponse<GHLUploadMediaFileResponse> = await this.axiosInstance.post(
|
|
'/medias/upload-file',
|
|
formData,
|
|
{
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
}
|
|
}
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete file or folder from media library
|
|
* DELETE /medias/{id}
|
|
*/
|
|
async deleteMediaFile(deleteParams: GHLDeleteMediaRequest): Promise<GHLApiResponse<GHLDeleteMediaResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altType: deleteParams.altType,
|
|
altId: deleteParams.altId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteMediaResponse> = await this.axiosInstance.delete(
|
|
`/medias/${deleteParams.id}?${queryParams}`
|
|
);
|
|
|
|
return this.wrapResponse({ success: true, message: 'Media file deleted successfully' });
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== CUSTOM OBJECTS API METHODS =====
|
|
|
|
/**
|
|
* Get all objects for a location
|
|
* GET /objects/
|
|
*/
|
|
async getObjectsByLocation(locationId?: string): Promise<GHLApiResponse<GHLObjectListResponse>> {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLObjectListResponse> = await this.axiosInstance.get(
|
|
'/objects/',
|
|
{ params }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom object schema
|
|
* POST /objects/
|
|
*/
|
|
async createObjectSchema(schemaData: GHLCreateObjectSchemaRequest): Promise<GHLApiResponse<GHLObjectSchemaResponse>> {
|
|
try {
|
|
const payload = {
|
|
...schemaData,
|
|
locationId: schemaData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLObjectSchemaResponse> = await this.axiosInstance.post(
|
|
'/objects/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get object schema by key/id
|
|
* GET /objects/{key}
|
|
*/
|
|
async getObjectSchema(params: GHLGetObjectSchemaRequest): Promise<GHLApiResponse<GHLGetObjectSchemaResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
...(params.fetchProperties !== undefined && { fetchProperties: params.fetchProperties.toString() })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetObjectSchemaResponse> = await this.axiosInstance.get(
|
|
`/objects/${params.key}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update object schema by key/id
|
|
* PUT /objects/{key}
|
|
*/
|
|
async updateObjectSchema(key: string, updateData: GHLUpdateObjectSchemaRequest): Promise<GHLApiResponse<GHLObjectSchemaResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLObjectSchemaResponse> = await this.axiosInstance.put(
|
|
`/objects/${key}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create object record
|
|
* POST /objects/{schemaKey}/records
|
|
*/
|
|
async createObjectRecord(schemaKey: string, recordData: GHLCreateObjectRecordRequest): Promise<GHLApiResponse<GHLDetailedObjectRecordResponse>> {
|
|
try {
|
|
const payload = {
|
|
...recordData,
|
|
locationId: recordData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLDetailedObjectRecordResponse> = await this.axiosInstance.post(
|
|
`/objects/${schemaKey}/records`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get object record by id
|
|
* GET /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async getObjectRecord(schemaKey: string, recordId: string): Promise<GHLApiResponse<GHLObjectRecordResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLObjectRecordResponse> = await this.axiosInstance.get(
|
|
`/objects/${schemaKey}/records/${recordId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update object record
|
|
* PUT /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async updateObjectRecord(schemaKey: string, recordId: string, updateData: GHLUpdateObjectRecordRequest): Promise<GHLApiResponse<GHLObjectRecordResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLObjectRecordResponse> = await this.axiosInstance.put(
|
|
`/objects/${schemaKey}/records/${recordId}`,
|
|
updateData,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete object record
|
|
* DELETE /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async deleteObjectRecord(schemaKey: string, recordId: string): Promise<GHLApiResponse<GHLObjectRecordDeleteResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLObjectRecordDeleteResponse> = await this.axiosInstance.delete(
|
|
`/objects/${schemaKey}/records/${recordId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search object records
|
|
* POST /objects/{schemaKey}/records/search
|
|
*/
|
|
async searchObjectRecords(schemaKey: string, searchData: GHLSearchObjectRecordsRequest): Promise<GHLApiResponse<GHLSearchObjectRecordsResponse>> {
|
|
try {
|
|
const payload = {
|
|
...searchData,
|
|
locationId: searchData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLSearchObjectRecordsResponse> = await this.axiosInstance.post(
|
|
`/objects/${schemaKey}/records/search`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== ASSOCIATIONS API METHODS =====
|
|
|
|
/**
|
|
* Get all associations for a location
|
|
* GET /associations/
|
|
*/
|
|
async getAssociations(params: GHLGetAssociationsRequest): Promise<GHLApiResponse<GHLGetAssociationsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
skip: params.skip.toString(),
|
|
limit: params.limit.toString()
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetAssociationsResponse> = await this.axiosInstance.get(
|
|
'/associations/',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create association
|
|
* POST /associations/
|
|
*/
|
|
async createAssociation(associationData: GHLCreateAssociationRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const payload = {
|
|
...associationData,
|
|
locationId: associationData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.post(
|
|
'/associations/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get association by ID
|
|
* GET /associations/{associationId}
|
|
*/
|
|
async getAssociationById(associationId: string): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.get(
|
|
`/associations/${associationId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update association
|
|
* PUT /associations/{associationId}
|
|
*/
|
|
async updateAssociation(associationId: string, updateData: GHLUpdateAssociationRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.put(
|
|
`/associations/${associationId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete association
|
|
* DELETE /associations/{associationId}
|
|
*/
|
|
async deleteAssociation(associationId: string): Promise<GHLApiResponse<GHLDeleteAssociationResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLDeleteAssociationResponse> = await this.axiosInstance.delete(
|
|
`/associations/${associationId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get association by key name
|
|
* GET /associations/key/{key_name}
|
|
*/
|
|
async getAssociationByKey(params: GHLGetAssociationByKeyRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.get(
|
|
`/associations/key/${params.keyName}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get association by object key
|
|
* GET /associations/objectKey/{objectKey}
|
|
*/
|
|
async getAssociationByObjectKey(params: GHLGetAssociationByObjectKeyRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const queryParams = params.locationId ? {
|
|
locationId: params.locationId
|
|
} : {};
|
|
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.get(
|
|
`/associations/objectKey/${params.objectKey}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create relation between entities
|
|
* POST /associations/relations
|
|
*/
|
|
async createRelation(relationData: GHLCreateRelationRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const payload = {
|
|
...relationData,
|
|
locationId: relationData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.post(
|
|
'/associations/relations',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get relations by record ID
|
|
* GET /associations/relations/{recordId}
|
|
*/
|
|
async getRelationsByRecord(params: GHLGetRelationsByRecordRequest): Promise<GHLApiResponse<GHLGetRelationsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
skip: params.skip.toString(),
|
|
limit: params.limit.toString(),
|
|
...(params.associationIds && { associationIds: params.associationIds })
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetRelationsResponse> = await this.axiosInstance.get(
|
|
`/associations/relations/${params.recordId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete relation
|
|
* DELETE /associations/relations/{relationId}
|
|
*/
|
|
async deleteRelation(params: GHLDeleteRelationRequest): Promise<GHLApiResponse<GHLAssociationResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLAssociationResponse> = await this.axiosInstance.delete(
|
|
`/associations/relations/${params.relationId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== CUSTOM FIELDS V2 API METHODS =====
|
|
|
|
/**
|
|
* Get custom field or folder by ID
|
|
* GET /custom-fields/{id}
|
|
*/
|
|
async getCustomFieldV2ById(id: string): Promise<GHLApiResponse<GHLV2CustomFieldResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLV2CustomFieldResponse> = await this.axiosInstance.get(
|
|
`/custom-fields/${id}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom field
|
|
* POST /custom-fields/
|
|
*/
|
|
async createCustomFieldV2(fieldData: GHLV2CreateCustomFieldRequest): Promise<GHLApiResponse<GHLV2CustomFieldResponse>> {
|
|
try {
|
|
const payload = {
|
|
...fieldData,
|
|
locationId: fieldData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2CustomFieldResponse> = await this.axiosInstance.post(
|
|
'/custom-fields/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update custom field by ID
|
|
* PUT /custom-fields/{id}
|
|
*/
|
|
async updateCustomFieldV2(id: string, fieldData: GHLV2UpdateCustomFieldRequest): Promise<GHLApiResponse<GHLV2CustomFieldResponse>> {
|
|
try {
|
|
const payload = {
|
|
...fieldData,
|
|
locationId: fieldData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2CustomFieldResponse> = await this.axiosInstance.put(
|
|
`/custom-fields/${id}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete custom field by ID
|
|
* DELETE /custom-fields/{id}
|
|
*/
|
|
async deleteCustomFieldV2(id: string): Promise<GHLApiResponse<GHLV2DeleteCustomFieldResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLV2DeleteCustomFieldResponse> = await this.axiosInstance.delete(
|
|
`/custom-fields/${id}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get custom fields by object key
|
|
* GET /custom-fields/object-key/{objectKey}
|
|
*/
|
|
async getCustomFieldsV2ByObjectKey(params: GHLV2GetCustomFieldsByObjectKeyRequest): Promise<GHLApiResponse<GHLV2CustomFieldsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2CustomFieldsResponse> = await this.axiosInstance.get(
|
|
`/custom-fields/object-key/${params.objectKey}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom field folder
|
|
* POST /custom-fields/folder
|
|
*/
|
|
async createCustomFieldV2Folder(folderData: GHLV2CreateCustomFieldFolderRequest): Promise<GHLApiResponse<GHLV2CustomFieldFolderResponse>> {
|
|
try {
|
|
const payload = {
|
|
...folderData,
|
|
locationId: folderData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2CustomFieldFolderResponse> = await this.axiosInstance.post(
|
|
'/custom-fields/folder',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update custom field folder name
|
|
* PUT /custom-fields/folder/{id}
|
|
*/
|
|
async updateCustomFieldV2Folder(id: string, folderData: GHLV2UpdateCustomFieldFolderRequest): Promise<GHLApiResponse<GHLV2CustomFieldFolderResponse>> {
|
|
try {
|
|
const payload = {
|
|
...folderData,
|
|
locationId: folderData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2CustomFieldFolderResponse> = await this.axiosInstance.put(
|
|
`/custom-fields/folder/${id}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete custom field folder
|
|
* DELETE /custom-fields/folder/{id}
|
|
*/
|
|
async deleteCustomFieldV2Folder(params: GHLV2DeleteCustomFieldFolderRequest): Promise<GHLApiResponse<GHLV2DeleteCustomFieldResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLV2DeleteCustomFieldResponse> = await this.axiosInstance.delete(
|
|
`/custom-fields/folder/${params.id}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== WORKFLOWS API METHODS =====
|
|
|
|
/**
|
|
* Get all workflows for a location
|
|
* GET /workflows/
|
|
*/
|
|
async getWorkflows(request: GHLGetWorkflowsRequest): Promise<GHLApiResponse<GHLGetWorkflowsResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
locationId: request.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetWorkflowsResponse> = await this.axiosInstance.get(
|
|
'/workflows/',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
// ===== SURVEYS API METHODS =====
|
|
|
|
/**
|
|
* Get all surveys for a location
|
|
* GET /surveys/
|
|
*/
|
|
async getSurveys(request: GHLGetSurveysRequest): Promise<GHLApiResponse<GHLGetSurveysResponse>> {
|
|
try {
|
|
const queryParams: Record<string, string> = {
|
|
locationId: request.locationId || this.config.locationId
|
|
};
|
|
|
|
if (request.skip !== undefined) {
|
|
queryParams.skip = request.skip.toString();
|
|
}
|
|
if (request.limit !== undefined) {
|
|
queryParams.limit = request.limit.toString();
|
|
}
|
|
if (request.type) {
|
|
queryParams.type = request.type;
|
|
}
|
|
|
|
const response: AxiosResponse<GHLGetSurveysResponse> = await this.axiosInstance.get(
|
|
'/surveys/',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw this.handleApiError(error as AxiosError<GHLErrorResponse>);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get survey submissions with filtering and pagination
|
|
* GET /surveys/submissions
|
|
*/
|
|
async getSurveySubmissions(request: GHLGetSurveySubmissionsRequest): Promise<GHLApiResponse<GHLGetSurveySubmissionsResponse>> {
|
|
try {
|
|
const locationId = request.locationId || this.config.locationId;
|
|
|
|
const params = new URLSearchParams();
|
|
if (request.page) params.append('page', request.page.toString());
|
|
if (request.limit) params.append('limit', request.limit.toString());
|
|
if (request.surveyId) params.append('surveyId', request.surveyId);
|
|
if (request.q) params.append('q', request.q);
|
|
if (request.startAt) params.append('startAt', request.startAt);
|
|
if (request.endAt) params.append('endAt', request.endAt);
|
|
|
|
const response: AxiosResponse<GHLGetSurveySubmissionsResponse> = await this.axiosInstance.get(
|
|
`/locations/${locationId}/surveys/submissions?${params.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ===== STORE API METHODS =====
|
|
|
|
/**
|
|
* SHIPPING ZONES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create a new shipping zone
|
|
* POST /store/shipping-zone
|
|
*/
|
|
async createShippingZone(zoneData: GHLCreateShippingZoneRequest): Promise<GHLApiResponse<GHLCreateShippingZoneResponse>> {
|
|
try {
|
|
const payload = {
|
|
...zoneData,
|
|
altId: zoneData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreateShippingZoneResponse> = await this.axiosInstance.post(
|
|
'/store/shipping-zone',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List all shipping zones
|
|
* GET /store/shipping-zone
|
|
*/
|
|
async listShippingZones(params: GHLGetShippingZonesRequest): Promise<GHLApiResponse<GHLListShippingZonesResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.withShippingRate !== undefined) queryParams.append('withShippingRate', params.withShippingRate.toString());
|
|
|
|
const response: AxiosResponse<GHLListShippingZonesResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-zone?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a specific shipping zone by ID
|
|
* GET /store/shipping-zone/{shippingZoneId}
|
|
*/
|
|
async getShippingZone(shippingZoneId: string, params: Omit<GHLGetShippingZonesRequest, 'limit' | 'offset'>): Promise<GHLApiResponse<GHLGetShippingZoneResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.withShippingRate !== undefined) queryParams.append('withShippingRate', params.withShippingRate.toString());
|
|
|
|
const response: AxiosResponse<GHLGetShippingZoneResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-zone/${shippingZoneId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a shipping zone
|
|
* PUT /store/shipping-zone/{shippingZoneId}
|
|
*/
|
|
async updateShippingZone(shippingZoneId: string, updateData: GHLUpdateShippingZoneRequest): Promise<GHLApiResponse<GHLUpdateShippingZoneResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateShippingZoneResponse> = await this.axiosInstance.put(
|
|
`/store/shipping-zone/${shippingZoneId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a shipping zone
|
|
* DELETE /store/shipping-zone/{shippingZoneId}
|
|
*/
|
|
async deleteShippingZone(shippingZoneId: string, params: GHLDeleteShippingZoneRequest): Promise<GHLApiResponse<GHLDeleteShippingZoneResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteShippingZoneResponse> = await this.axiosInstance.delete(
|
|
`/store/shipping-zone/${shippingZoneId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SHIPPING RATES API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Get available shipping rates for an order
|
|
* POST /store/shipping-zone/shipping-rates
|
|
*/
|
|
async getAvailableShippingRates(rateData: GHLGetAvailableShippingRatesRequest): Promise<GHLApiResponse<GHLGetAvailableShippingRatesResponse>> {
|
|
try {
|
|
const payload = {
|
|
...rateData,
|
|
altId: rateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLGetAvailableShippingRatesResponse> = await this.axiosInstance.post(
|
|
'/store/shipping-zone/shipping-rates',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new shipping rate for a zone
|
|
* POST /store/shipping-zone/{shippingZoneId}/shipping-rate
|
|
*/
|
|
async createShippingRate(shippingZoneId: string, rateData: GHLCreateShippingRateRequest): Promise<GHLApiResponse<GHLCreateShippingRateResponse>> {
|
|
try {
|
|
const payload = {
|
|
...rateData,
|
|
altId: rateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreateShippingRateResponse> = await this.axiosInstance.post(
|
|
`/store/shipping-zone/${shippingZoneId}/shipping-rate`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List shipping rates for a zone
|
|
* GET /store/shipping-zone/{shippingZoneId}/shipping-rate
|
|
*/
|
|
async listShippingRates(shippingZoneId: string, params: GHLGetShippingRatesRequest): Promise<GHLApiResponse<GHLListShippingRatesResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
|
|
const response: AxiosResponse<GHLListShippingRatesResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-zone/${shippingZoneId}/shipping-rate?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a specific shipping rate
|
|
* GET /store/shipping-zone/{shippingZoneId}/shipping-rate/{shippingRateId}
|
|
*/
|
|
async getShippingRate(shippingZoneId: string, shippingRateId: string, params: Omit<GHLGetShippingRatesRequest, 'limit' | 'offset'>): Promise<GHLApiResponse<GHLGetShippingRateResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetShippingRateResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-zone/${shippingZoneId}/shipping-rate/${shippingRateId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a shipping rate
|
|
* PUT /store/shipping-zone/{shippingZoneId}/shipping-rate/{shippingRateId}
|
|
*/
|
|
async updateShippingRate(shippingZoneId: string, shippingRateId: string, updateData: GHLUpdateShippingRateRequest): Promise<GHLApiResponse<GHLUpdateShippingRateResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateShippingRateResponse> = await this.axiosInstance.put(
|
|
`/store/shipping-zone/${shippingZoneId}/shipping-rate/${shippingRateId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a shipping rate
|
|
* DELETE /store/shipping-zone/{shippingZoneId}/shipping-rate/{shippingRateId}
|
|
*/
|
|
async deleteShippingRate(shippingZoneId: string, shippingRateId: string, params: GHLDeleteShippingRateRequest): Promise<GHLApiResponse<GHLDeleteShippingRateResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteShippingRateResponse> = await this.axiosInstance.delete(
|
|
`/store/shipping-zone/${shippingZoneId}/shipping-rate/${shippingRateId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* SHIPPING CARRIERS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create a new shipping carrier
|
|
* POST /store/shipping-carrier
|
|
*/
|
|
async createShippingCarrier(carrierData: GHLCreateShippingCarrierRequest): Promise<GHLApiResponse<GHLCreateShippingCarrierResponse>> {
|
|
try {
|
|
const payload = {
|
|
...carrierData,
|
|
altId: carrierData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreateShippingCarrierResponse> = await this.axiosInstance.post(
|
|
'/store/shipping-carrier',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List all shipping carriers
|
|
* GET /store/shipping-carrier
|
|
*/
|
|
async listShippingCarriers(params: GHLGetShippingCarriersRequest): Promise<GHLApiResponse<GHLListShippingCarriersResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLListShippingCarriersResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-carrier?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a specific shipping carrier by ID
|
|
* GET /store/shipping-carrier/{shippingCarrierId}
|
|
*/
|
|
async getShippingCarrier(shippingCarrierId: string, params: GHLGetShippingCarriersRequest): Promise<GHLApiResponse<GHLGetShippingCarrierResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetShippingCarrierResponse> = await this.axiosInstance.get(
|
|
`/store/shipping-carrier/${shippingCarrierId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a shipping carrier
|
|
* PUT /store/shipping-carrier/{shippingCarrierId}
|
|
*/
|
|
async updateShippingCarrier(shippingCarrierId: string, updateData: GHLUpdateShippingCarrierRequest): Promise<GHLApiResponse<GHLUpdateShippingCarrierResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateShippingCarrierResponse> = await this.axiosInstance.put(
|
|
`/store/shipping-carrier/${shippingCarrierId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a shipping carrier
|
|
* DELETE /store/shipping-carrier/{shippingCarrierId}
|
|
*/
|
|
async deleteShippingCarrier(shippingCarrierId: string, params: GHLDeleteShippingCarrierRequest): Promise<GHLApiResponse<GHLDeleteShippingCarrierResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteShippingCarrierResponse> = await this.axiosInstance.delete(
|
|
`/store/shipping-carrier/${shippingCarrierId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* STORE SETTINGS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create or update store settings
|
|
* POST /store/store-setting
|
|
*/
|
|
async createStoreSetting(settingData: GHLCreateStoreSettingRequest): Promise<GHLApiResponse<GHLCreateStoreSettingResponse>> {
|
|
try {
|
|
const payload = {
|
|
...settingData,
|
|
altId: settingData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreateStoreSettingResponse> = await this.axiosInstance.post(
|
|
'/store/store-setting',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get store settings
|
|
* GET /store/store-setting
|
|
*/
|
|
async getStoreSetting(params: GHLGetStoreSettingRequest): Promise<GHLApiResponse<GHLGetStoreSettingResponse>> {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetStoreSettingResponse> = await this.axiosInstance.get(
|
|
`/store/store-setting?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PRODUCTS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create a new product
|
|
* POST /products/
|
|
*/
|
|
async createProduct(productData: GHLCreateProductRequest): Promise<GHLApiResponse<GHLCreateProductResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLCreateProductResponse> = await this.axiosInstance.post(
|
|
'/products/',
|
|
productData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a product by ID
|
|
* PUT /products/{productId}
|
|
*/
|
|
async updateProduct(productId: string, updateData: GHLUpdateProductRequest): Promise<GHLApiResponse<GHLUpdateProductResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLUpdateProductResponse> = await this.axiosInstance.put(
|
|
`/products/${productId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a product by ID
|
|
* GET /products/{productId}
|
|
*/
|
|
async getProduct(productId: string, locationId?: string): Promise<GHLApiResponse<GHLGetProductResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetProductResponse> = await this.axiosInstance.get(
|
|
`/products/${productId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List products
|
|
* GET /products/
|
|
*/
|
|
async listProducts(params: GHLListProductsRequest): Promise<GHLApiResponse<GHLListProductsResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: params.locationId || this.config.locationId
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.search) queryParams.append('search', params.search);
|
|
if (params.collectionIds?.length) queryParams.append('collectionIds', params.collectionIds.join(','));
|
|
if (params.collectionSlug) queryParams.append('collectionSlug', params.collectionSlug);
|
|
if (params.expand?.length) params.expand.forEach(item => queryParams.append('expand', item));
|
|
if (params.productIds?.length) params.productIds.forEach(id => queryParams.append('productIds', id));
|
|
if (params.storeId) queryParams.append('storeId', params.storeId);
|
|
if (params.includedInStore !== undefined) queryParams.append('includedInStore', params.includedInStore.toString());
|
|
if (params.availableInStore !== undefined) queryParams.append('availableInStore', params.availableInStore.toString());
|
|
if (params.sortOrder) queryParams.append('sortOrder', params.sortOrder);
|
|
|
|
const response: AxiosResponse<GHLListProductsResponse> = await this.axiosInstance.get(
|
|
`/products/?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a product by ID
|
|
* DELETE /products/{productId}
|
|
*/
|
|
async deleteProduct(productId: string, locationId?: string): Promise<GHLApiResponse<GHLDeleteProductResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteProductResponse> = await this.axiosInstance.delete(
|
|
`/products/${productId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk update products
|
|
* POST /products/bulk-update
|
|
*/
|
|
async bulkUpdateProducts(updateData: GHLBulkUpdateRequest): Promise<GHLApiResponse<GHLBulkUpdateResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLBulkUpdateResponse> = await this.axiosInstance.post(
|
|
'/products/bulk-update',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a price for a product
|
|
* POST /products/{productId}/price
|
|
*/
|
|
async createPrice(productId: string, priceData: GHLCreatePriceRequest): Promise<GHLApiResponse<GHLCreatePriceResponse>> {
|
|
try {
|
|
const payload = {
|
|
...priceData,
|
|
locationId: priceData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreatePriceResponse> = await this.axiosInstance.post(
|
|
`/products/${productId}/price`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a price by ID
|
|
* PUT /products/{productId}/price/{priceId}
|
|
*/
|
|
async updatePrice(productId: string, priceId: string, updateData: GHLUpdatePriceRequest): Promise<GHLApiResponse<GHLUpdatePriceResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdatePriceResponse> = await this.axiosInstance.put(
|
|
`/products/${productId}/price/${priceId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a price by ID
|
|
* GET /products/{productId}/price/{priceId}
|
|
*/
|
|
async getPrice(productId: string, priceId: string, locationId?: string): Promise<GHLApiResponse<GHLGetPriceResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLGetPriceResponse> = await this.axiosInstance.get(
|
|
`/products/${productId}/price/${priceId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List prices for a product
|
|
* GET /products/{productId}/price
|
|
*/
|
|
async listPrices(productId: string, params: GHLListPricesRequest): Promise<GHLApiResponse<GHLListPricesResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: params.locationId || this.config.locationId
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.ids) queryParams.append('ids', params.ids);
|
|
|
|
const response: AxiosResponse<GHLListPricesResponse> = await this.axiosInstance.get(
|
|
`/products/${productId}/price?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a price by ID
|
|
* DELETE /products/{productId}/price/{priceId}
|
|
*/
|
|
async deletePrice(productId: string, priceId: string, locationId?: string): Promise<GHLApiResponse<GHLDeletePriceResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeletePriceResponse> = await this.axiosInstance.delete(
|
|
`/products/${productId}/price/${priceId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List inventory
|
|
* GET /products/inventory
|
|
*/
|
|
async listInventory(params: GHLListInventoryRequest): Promise<GHLApiResponse<GHLListInventoryResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.search) queryParams.append('search', params.search);
|
|
|
|
const response: AxiosResponse<GHLListInventoryResponse> = await this.axiosInstance.get(
|
|
`/products/inventory?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update inventory
|
|
* POST /products/inventory
|
|
*/
|
|
async updateInventory(updateData: GHLUpdateInventoryRequest): Promise<GHLApiResponse<GHLUpdateInventoryResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateInventoryResponse> = await this.axiosInstance.post(
|
|
'/products/inventory',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get product store stats
|
|
* GET /products/store/{storeId}/stats
|
|
*/
|
|
async getProductStoreStats(storeId: string, params: GHLGetProductStoreStatsRequest): Promise<GHLApiResponse<GHLGetProductStoreStatsResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.search) queryParams.append('search', params.search);
|
|
if (params.collectionIds) queryParams.append('collectionIds', params.collectionIds);
|
|
|
|
const response: AxiosResponse<GHLGetProductStoreStatsResponse> = await this.axiosInstance.get(
|
|
`/products/store/${storeId}/stats?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update product store status
|
|
* POST /products/store/{storeId}
|
|
*/
|
|
async updateProductStore(storeId: string, updateData: GHLUpdateProductStoreRequest): Promise<GHLApiResponse<GHLUpdateProductStoreResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLUpdateProductStoreResponse> = await this.axiosInstance.post(
|
|
`/products/store/${storeId}`,
|
|
updateData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a product collection
|
|
* POST /products/collections
|
|
*/
|
|
async createProductCollection(collectionData: GHLCreateProductCollectionRequest): Promise<GHLApiResponse<GHLCreateCollectionResponse>> {
|
|
try {
|
|
const payload = {
|
|
...collectionData,
|
|
altId: collectionData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLCreateCollectionResponse> = await this.axiosInstance.post(
|
|
'/products/collections',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a product collection
|
|
* PUT /products/collections/{collectionId}
|
|
*/
|
|
async updateProductCollection(collectionId: string, updateData: GHLUpdateProductCollectionRequest): Promise<GHLApiResponse<GHLUpdateProductCollectionResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateProductCollectionResponse> = await this.axiosInstance.put(
|
|
`/products/collections/${collectionId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a product collection by ID
|
|
* GET /products/collections/{collectionId}
|
|
*/
|
|
async getProductCollection(collectionId: string): Promise<GHLApiResponse<GHLDefaultCollectionResponse>> {
|
|
try {
|
|
const response: AxiosResponse<GHLDefaultCollectionResponse> = await this.axiosInstance.get(
|
|
`/products/collections/${collectionId}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List product collections
|
|
* GET /products/collections
|
|
*/
|
|
async listProductCollections(params: GHLListProductCollectionsRequest): Promise<GHLApiResponse<GHLListCollectionResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.collectionIds) queryParams.append('collectionIds', params.collectionIds);
|
|
if (params.name) queryParams.append('name', params.name);
|
|
|
|
const response: AxiosResponse<GHLListCollectionResponse> = await this.axiosInstance.get(
|
|
`/products/collections?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a product collection
|
|
* DELETE /products/collections/{collectionId}
|
|
*/
|
|
async deleteProductCollection(collectionId: string, params: GHLDeleteProductCollectionRequest): Promise<GHLApiResponse<GHLDeleteProductCollectionResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteProductCollectionResponse> = await this.axiosInstance.delete(
|
|
`/products/collections/${collectionId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List product reviews
|
|
* GET /products/reviews
|
|
*/
|
|
async listProductReviews(params: GHLListProductReviewsRequest): Promise<GHLApiResponse<GHLListProductReviewsResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.limit) queryParams.append('limit', params.limit.toString());
|
|
if (params.offset) queryParams.append('offset', params.offset.toString());
|
|
if (params.sortField) queryParams.append('sortField', params.sortField);
|
|
if (params.sortOrder) queryParams.append('sortOrder', params.sortOrder);
|
|
if (params.rating) queryParams.append('rating', params.rating.toString());
|
|
if (params.startDate) queryParams.append('startDate', params.startDate);
|
|
if (params.endDate) queryParams.append('endDate', params.endDate);
|
|
if (params.productId) queryParams.append('productId', params.productId);
|
|
if (params.storeId) queryParams.append('storeId', params.storeId);
|
|
|
|
const response: AxiosResponse<GHLListProductReviewsResponse> = await this.axiosInstance.get(
|
|
`/products/reviews?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get reviews count
|
|
* GET /products/reviews/count
|
|
*/
|
|
async getReviewsCount(params: GHLGetReviewsCountRequest): Promise<GHLApiResponse<GHLCountReviewsByStatusResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
|
|
if (params.rating) queryParams.append('rating', params.rating.toString());
|
|
if (params.startDate) queryParams.append('startDate', params.startDate);
|
|
if (params.endDate) queryParams.append('endDate', params.endDate);
|
|
if (params.productId) queryParams.append('productId', params.productId);
|
|
if (params.storeId) queryParams.append('storeId', params.storeId);
|
|
|
|
const response: AxiosResponse<GHLCountReviewsByStatusResponse> = await this.axiosInstance.get(
|
|
`/products/reviews/count?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a product review
|
|
* PUT /products/reviews/{reviewId}
|
|
*/
|
|
async updateProductReview(reviewId: string, updateData: GHLUpdateProductReviewRequest): Promise<GHLApiResponse<GHLUpdateProductReviewsResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateProductReviewsResponse> = await this.axiosInstance.put(
|
|
`/products/reviews/${reviewId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a product review
|
|
* DELETE /products/reviews/{reviewId}
|
|
*/
|
|
async deleteProductReview(reviewId: string, params: GHLDeleteProductReviewRequest): Promise<GHLApiResponse<GHLDeleteProductReviewResponse>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location',
|
|
productId: params.productId
|
|
});
|
|
|
|
const response: AxiosResponse<GHLDeleteProductReviewResponse> = await this.axiosInstance.delete(
|
|
`/products/reviews/${reviewId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk update product reviews
|
|
* POST /products/reviews/bulk-update
|
|
*/
|
|
async bulkUpdateProductReviews(updateData: GHLBulkUpdateProductReviewsRequest): Promise<GHLApiResponse<GHLUpdateProductReviewsResponse>> {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GHLUpdateProductReviewsResponse> = await this.axiosInstance.post(
|
|
'/products/reviews/bulk-update',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PAYMENTS API METHODS
|
|
*/
|
|
|
|
/**
|
|
* Create white-label integration provider
|
|
* POST /payments/integrations/provider/whitelabel
|
|
*/
|
|
async createWhiteLabelIntegrationProvider(data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
'/payments/integrations/provider/whitelabel',
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List white-label integration providers
|
|
* GET /payments/integrations/provider/whitelabel
|
|
*/
|
|
async listWhiteLabelIntegrationProviders(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/integrations/provider/whitelabel?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List orders
|
|
* GET /payments/orders
|
|
*/
|
|
async listOrders(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/orders?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get order by ID
|
|
* GET /payments/orders/{orderId}
|
|
*/
|
|
async getOrderById(orderId: string, params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null && key !== 'orderId') {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/orders/${orderId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create order fulfillment
|
|
* POST /payments/orders/{orderId}/fulfillments
|
|
*/
|
|
async createOrderFulfillment(orderId: string, data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/payments/orders/${orderId}/fulfillments`,
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List order fulfillments
|
|
* GET /payments/orders/{orderId}/fulfillments
|
|
*/
|
|
async listOrderFulfillments(orderId: string, params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null && key !== 'orderId') {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/orders/${orderId}/fulfillments?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List transactions
|
|
* GET /payments/transactions
|
|
*/
|
|
async listTransactions(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/transactions?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get transaction by ID
|
|
* GET /payments/transactions/{transactionId}
|
|
*/
|
|
async getTransactionById(transactionId: string, params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null && key !== 'transactionId') {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/transactions/${transactionId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List subscriptions
|
|
* GET /payments/subscriptions
|
|
*/
|
|
async listSubscriptions(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/subscriptions?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get subscription by ID
|
|
* GET /payments/subscriptions/{subscriptionId}
|
|
*/
|
|
async getSubscriptionById(subscriptionId: string, params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null && key !== 'subscriptionId') {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/subscriptions/${subscriptionId}?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List coupons
|
|
* GET /payments/coupon/list
|
|
*/
|
|
async listCoupons(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/coupon/list?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create coupon
|
|
* POST /payments/coupon
|
|
*/
|
|
async createCoupon(data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
'/payments/coupon',
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update coupon
|
|
* PUT /payments/coupon
|
|
*/
|
|
async updateCoupon(data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.put(
|
|
'/payments/coupon',
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete coupon
|
|
* DELETE /payments/coupon
|
|
*/
|
|
async deleteCoupon(data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
'/payments/coupon',
|
|
{ data }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get coupon
|
|
* GET /payments/coupon
|
|
*/
|
|
async getCoupon(params: Record<string, any>): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/coupon?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom provider integration
|
|
* POST /payments/custom-provider/provider
|
|
*/
|
|
async createCustomProviderIntegration(locationId: string, data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/payments/custom-provider/provider?${queryParams.toString()}`,
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete custom provider integration
|
|
* DELETE /payments/custom-provider/provider
|
|
*/
|
|
async deleteCustomProviderIntegration(locationId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.delete(
|
|
`/payments/custom-provider/provider?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get custom provider config
|
|
* GET /payments/custom-provider/connect
|
|
*/
|
|
async getCustomProviderConfig(locationId: string): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.get(
|
|
`/payments/custom-provider/connect?${queryParams.toString()}`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create custom provider config
|
|
* POST /payments/custom-provider/connect
|
|
*/
|
|
async createCustomProviderConfig(locationId: string, data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/payments/custom-provider/connect?${queryParams.toString()}`,
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disconnect custom provider config
|
|
* POST /payments/custom-provider/disconnect
|
|
*/
|
|
async disconnectCustomProviderConfig(locationId: string, data: any): Promise<GHLApiResponse<any>> {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
|
|
const response: AxiosResponse<any> = await this.axiosInstance.post(
|
|
`/payments/custom-provider/disconnect?${queryParams.toString()}`,
|
|
data
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// INVOICES API METHODS
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Create invoice template
|
|
* POST /invoices/template
|
|
*/
|
|
async createInvoiceTemplate(templateData: CreateInvoiceTemplateDto): Promise<GHLApiResponse<CreateInvoiceTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<CreateInvoiceTemplateResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/template',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List invoice templates
|
|
* GET /invoices/template
|
|
*/
|
|
async listInvoiceTemplates(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
status?: string;
|
|
startAt?: string;
|
|
endAt?: string;
|
|
search?: string;
|
|
paymentMode?: 'default' | 'live' | 'test';
|
|
limit: string;
|
|
offset: string;
|
|
}): Promise<GHLApiResponse<ListTemplatesResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.status && { status: params.status }),
|
|
...(params?.startAt && { startAt: params.startAt }),
|
|
...(params?.endAt && { endAt: params.endAt }),
|
|
...(params?.search && { search: params.search }),
|
|
...(params?.paymentMode && { paymentMode: params.paymentMode })
|
|
};
|
|
|
|
const response: AxiosResponse<ListTemplatesResponse> = await this.axiosInstance.get(
|
|
'/invoices/template',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get invoice template by ID
|
|
* GET /invoices/template/{templateId}
|
|
*/
|
|
async getInvoiceTemplate(templateId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<InvoiceTemplate>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<InvoiceTemplate> = await this.axiosInstance.get(
|
|
`/invoices/template/${templateId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice template
|
|
* PUT /invoices/template/{templateId}
|
|
*/
|
|
async updateInvoiceTemplate(templateId: string, templateData: UpdateInvoiceTemplateDto): Promise<GHLApiResponse<UpdateInvoiceTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceTemplateResponseDto> = await this.axiosInstance.put(
|
|
`/invoices/template/${templateId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete invoice template
|
|
* DELETE /invoices/template/{templateId}
|
|
*/
|
|
async deleteInvoiceTemplate(templateId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<DeleteInvoiceTemplateResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<DeleteInvoiceTemplateResponseDto> = await this.axiosInstance.delete(
|
|
`/invoices/template/${templateId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice template late fees configuration
|
|
* PATCH /invoices/template/{templateId}/late-fees-configuration
|
|
*/
|
|
async updateInvoiceTemplateLateFeesConfiguration(templateId: string, configData: UpdateInvoiceLateFeesConfigurationDto): Promise<GHLApiResponse<UpdateInvoiceTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceTemplateResponseDto> = await this.axiosInstance.patch(
|
|
`/invoices/template/${templateId}/late-fees-configuration`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice template payment methods configuration
|
|
* PATCH /invoices/template/{templateId}/payment-methods-configuration
|
|
*/
|
|
async updateInvoiceTemplatePaymentMethodsConfiguration(templateId: string, configData: UpdatePaymentMethodsConfigurationDto): Promise<GHLApiResponse<UpdateInvoiceTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceTemplateResponseDto> = await this.axiosInstance.patch(
|
|
`/invoices/template/${templateId}/payment-methods-configuration`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create invoice schedule
|
|
* POST /invoices/schedule
|
|
*/
|
|
async createInvoiceSchedule(scheduleData: CreateInvoiceScheduleDto): Promise<GHLApiResponse<CreateInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<CreateInvoiceScheduleResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/schedule',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List invoice schedules
|
|
* GET /invoices/schedule
|
|
*/
|
|
async listInvoiceSchedules(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
status?: string;
|
|
startAt?: string;
|
|
endAt?: string;
|
|
search?: string;
|
|
paymentMode?: 'default' | 'live' | 'test';
|
|
limit: string;
|
|
offset: string;
|
|
}): Promise<GHLApiResponse<ListSchedulesResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.status && { status: params.status }),
|
|
...(params?.startAt && { startAt: params.startAt }),
|
|
...(params?.endAt && { endAt: params.endAt }),
|
|
...(params?.search && { search: params.search }),
|
|
...(params?.paymentMode && { paymentMode: params.paymentMode })
|
|
};
|
|
|
|
const response: AxiosResponse<ListSchedulesResponse> = await this.axiosInstance.get(
|
|
'/invoices/schedule',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get invoice schedule by ID
|
|
* GET /invoices/schedule/{scheduleId}
|
|
*/
|
|
async getInvoiceSchedule(scheduleId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<GetScheduleResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GetScheduleResponseDto> = await this.axiosInstance.get(
|
|
`/invoices/schedule/${scheduleId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice schedule
|
|
* PUT /invoices/schedule/{scheduleId}
|
|
*/
|
|
async updateInvoiceSchedule(scheduleId: string, scheduleData: UpdateInvoiceScheduleDto): Promise<GHLApiResponse<UpdateInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceScheduleResponseDto> = await this.axiosInstance.put(
|
|
`/invoices/schedule/${scheduleId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete invoice schedule
|
|
* DELETE /invoices/schedule/{scheduleId}
|
|
*/
|
|
async deleteInvoiceSchedule(scheduleId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<DeleteInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<DeleteInvoiceScheduleResponseDto> = await this.axiosInstance.delete(
|
|
`/invoices/schedule/${scheduleId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update and schedule recurring invoice
|
|
* POST /invoices/schedule/{scheduleId}/updateAndSchedule
|
|
*/
|
|
async updateAndScheduleInvoiceSchedule(scheduleId: string): Promise<GHLApiResponse<UpdateAndScheduleInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const response: AxiosResponse<UpdateAndScheduleInvoiceScheduleResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/schedule/${scheduleId}/updateAndSchedule`
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Schedule an invoice schedule
|
|
* POST /invoices/schedule/{scheduleId}/schedule
|
|
*/
|
|
async scheduleInvoiceSchedule(scheduleId: string, scheduleData: ScheduleInvoiceScheduleDto): Promise<GHLApiResponse<ScheduleInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<ScheduleInvoiceScheduleResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/schedule/${scheduleId}/schedule`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Manage auto payment for schedule invoice
|
|
* POST /invoices/schedule/{scheduleId}/auto-payment
|
|
*/
|
|
async autoPaymentInvoiceSchedule(scheduleId: string, paymentData: AutoPaymentScheduleDto): Promise<GHLApiResponse<AutoPaymentInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...paymentData,
|
|
altId: paymentData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<AutoPaymentInvoiceScheduleResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/schedule/${scheduleId}/auto-payment`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancel scheduled invoice
|
|
* POST /invoices/schedule/{scheduleId}/cancel
|
|
*/
|
|
async cancelInvoiceSchedule(scheduleId: string, cancelData: CancelInvoiceScheduleDto): Promise<GHLApiResponse<CancelInvoiceScheduleResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...cancelData,
|
|
altId: cancelData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<CancelInvoiceScheduleResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/schedule/${scheduleId}/cancel`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create or update text2pay invoice
|
|
* POST /invoices/text2pay
|
|
*/
|
|
async text2PayInvoice(invoiceData: Text2PayDto): Promise<GHLApiResponse<Text2PayInvoiceResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<Text2PayInvoiceResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/text2pay',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate invoice number
|
|
* GET /invoices/generate-invoice-number
|
|
*/
|
|
async generateInvoiceNumber(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<GenerateInvoiceNumberResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GenerateInvoiceNumberResponse> = await this.axiosInstance.get(
|
|
'/invoices/generate-invoice-number',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get invoice by ID
|
|
* GET /invoices/{invoiceId}
|
|
*/
|
|
async getInvoice(invoiceId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<GetInvoiceResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GetInvoiceResponseDto> = await this.axiosInstance.get(
|
|
`/invoices/${invoiceId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice
|
|
* PUT /invoices/{invoiceId}
|
|
*/
|
|
async updateInvoice(invoiceId: string, invoiceData: UpdateInvoiceDto): Promise<GHLApiResponse<UpdateInvoiceResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceResponseDto> = await this.axiosInstance.put(
|
|
`/invoices/${invoiceId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete invoice
|
|
* DELETE /invoices/{invoiceId}
|
|
*/
|
|
async deleteInvoice(invoiceId: string, params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<DeleteInvoiceResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<DeleteInvoiceResponseDto> = await this.axiosInstance.delete(
|
|
`/invoices/${invoiceId}`,
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice late fees configuration
|
|
* PATCH /invoices/{invoiceId}/late-fees-configuration
|
|
*/
|
|
async updateInvoiceLateFeesConfiguration(invoiceId: string, configData: UpdateInvoiceLateFeesConfigurationDto): Promise<GHLApiResponse<UpdateInvoiceResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<UpdateInvoiceResponseDto> = await this.axiosInstance.patch(
|
|
`/invoices/${invoiceId}/late-fees-configuration`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Void invoice
|
|
* POST /invoices/{invoiceId}/void
|
|
*/
|
|
async voidInvoice(invoiceId: string, voidData: VoidInvoiceDto): Promise<GHLApiResponse<VoidInvoiceResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...voidData,
|
|
altId: voidData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<VoidInvoiceResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/${invoiceId}/void`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send invoice
|
|
* POST /invoices/{invoiceId}/send
|
|
*/
|
|
async sendInvoice(invoiceId: string, sendData: SendInvoiceDto): Promise<GHLApiResponse<SendInvoicesResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...sendData,
|
|
altId: sendData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<SendInvoicesResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/${invoiceId}/send`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Record manual payment for invoice
|
|
* POST /invoices/{invoiceId}/record-payment
|
|
*/
|
|
async recordInvoicePayment(invoiceId: string, paymentData: RecordPaymentDto): Promise<GHLApiResponse<RecordPaymentResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...paymentData,
|
|
altId: paymentData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<RecordPaymentResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/${invoiceId}/record-payment`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update invoice last visited at
|
|
* PATCH /invoices/stats/last-visited-at
|
|
*/
|
|
async updateInvoiceLastVisitedAt(statsData: PatchInvoiceStatsLastViewedDto): Promise<GHLApiResponse<void>> {
|
|
try {
|
|
const response: AxiosResponse<void> = await this.axiosInstance.patch(
|
|
'/invoices/stats/last-visited-at',
|
|
statsData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create new estimate
|
|
* POST /invoices/estimate
|
|
*/
|
|
async createEstimate(estimateData: CreateEstimatesDto): Promise<GHLApiResponse<EstimateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...estimateData,
|
|
altId: estimateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/estimate',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update estimate
|
|
* PUT /invoices/estimate/{estimateId}
|
|
*/
|
|
async updateEstimate(estimateId: string, estimateData: UpdateEstimateDto): Promise<GHLApiResponse<EstimateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...estimateData,
|
|
altId: estimateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateResponseDto> = await this.axiosInstance.put(
|
|
`/invoices/estimate/${estimateId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete estimate
|
|
* DELETE /invoices/estimate/{estimateId}
|
|
*/
|
|
async deleteEstimate(estimateId: string, deleteData: AltDto): Promise<GHLApiResponse<EstimateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...deleteData,
|
|
altId: deleteData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateResponseDto> = await this.axiosInstance.delete(
|
|
`/invoices/estimate/${estimateId}`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate estimate number
|
|
* GET /invoices/estimate/number/generate
|
|
*/
|
|
async generateEstimateNumber(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
}): Promise<GHLApiResponse<GenerateEstimateNumberResponse>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<GenerateEstimateNumberResponse> = await this.axiosInstance.get(
|
|
'/invoices/estimate/number/generate',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send estimate
|
|
* POST /invoices/estimate/{estimateId}/send
|
|
*/
|
|
async sendEstimate(estimateId: string, sendData: SendEstimateDto): Promise<GHLApiResponse<EstimateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...sendData,
|
|
altId: sendData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/estimate/${estimateId}/send`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create invoice from estimate
|
|
* POST /invoices/estimate/{estimateId}/invoice
|
|
*/
|
|
async createInvoiceFromEstimate(estimateId: string, invoiceData: CreateInvoiceFromEstimateDto): Promise<GHLApiResponse<CreateInvoiceFromEstimateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<CreateInvoiceFromEstimateResponseDto> = await this.axiosInstance.post(
|
|
`/invoices/estimate/${estimateId}/invoice`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List estimates
|
|
* GET /invoices/estimate/list
|
|
*/
|
|
async listEstimates(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
startAt?: string;
|
|
endAt?: string;
|
|
search?: string;
|
|
status?: 'all' | 'draft' | 'sent' | 'accepted' | 'declined' | 'invoiced' | 'viewed';
|
|
contactId?: string;
|
|
limit: string;
|
|
offset: string;
|
|
}): Promise<GHLApiResponse<ListEstimatesResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.startAt && { startAt: params.startAt }),
|
|
...(params?.endAt && { endAt: params.endAt }),
|
|
...(params?.search && { search: params.search }),
|
|
...(params?.status && { status: params.status }),
|
|
...(params?.contactId && { contactId: params.contactId })
|
|
};
|
|
|
|
const response: AxiosResponse<ListEstimatesResponseDto> = await this.axiosInstance.get(
|
|
'/invoices/estimate/list',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update estimate last visited at
|
|
* PATCH /invoices/estimate/stats/last-visited-at
|
|
*/
|
|
async updateEstimateLastVisitedAt(statsData: EstimateIdParam): Promise<GHLApiResponse<void>> {
|
|
try {
|
|
const response: AxiosResponse<void> = await this.axiosInstance.patch(
|
|
'/invoices/estimate/stats/last-visited-at',
|
|
statsData
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List estimate templates
|
|
* GET /invoices/estimate/template
|
|
*/
|
|
async listEstimateTemplates(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
search?: string;
|
|
limit: string;
|
|
offset: string;
|
|
}): Promise<GHLApiResponse<ListEstimateTemplateResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.search && { search: params.search })
|
|
};
|
|
|
|
const response: AxiosResponse<ListEstimateTemplateResponseDto> = await this.axiosInstance.get(
|
|
'/invoices/estimate/template',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create estimate template
|
|
* POST /invoices/estimate/template
|
|
*/
|
|
async createEstimateTemplate(templateData: EstimateTemplatesDto): Promise<GHLApiResponse<EstimateTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateTemplateResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/estimate/template',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update estimate template
|
|
* PUT /invoices/estimate/template/{templateId}
|
|
*/
|
|
async updateEstimateTemplate(templateId: string, templateData: EstimateTemplatesDto): Promise<GHLApiResponse<EstimateTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateTemplateResponseDto> = await this.axiosInstance.put(
|
|
`/invoices/estimate/template/${templateId}`,
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete estimate template
|
|
* DELETE /invoices/estimate/template/{templateId}
|
|
*/
|
|
async deleteEstimateTemplate(templateId: string, deleteData: AltDto): Promise<GHLApiResponse<EstimateTemplateResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...deleteData,
|
|
altId: deleteData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateTemplateResponseDto> = await this.axiosInstance.delete(
|
|
`/invoices/estimate/template/${templateId}`,
|
|
{ data: payload }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Preview estimate template
|
|
* GET /invoices/estimate/template/preview
|
|
*/
|
|
async previewEstimateTemplate(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
templateId: string;
|
|
}): Promise<GHLApiResponse<EstimateTemplateResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
templateId: params?.templateId || ''
|
|
};
|
|
|
|
const response: AxiosResponse<EstimateTemplateResponseDto> = await this.axiosInstance.get(
|
|
'/invoices/estimate/template/preview',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create invoice
|
|
* POST /invoices/
|
|
*/
|
|
async createInvoice(invoiceData: CreateInvoiceDto): Promise<GHLApiResponse<CreateInvoiceResponseDto>> {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location' as const
|
|
};
|
|
|
|
const response: AxiosResponse<CreateInvoiceResponseDto> = await this.axiosInstance.post(
|
|
'/invoices/',
|
|
payload
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List invoices
|
|
* GET /invoices/
|
|
*/
|
|
async listInvoices(params?: {
|
|
altId?: string;
|
|
altType?: 'location';
|
|
status?: string;
|
|
startAt?: string;
|
|
endAt?: string;
|
|
search?: string;
|
|
paymentMode?: 'default' | 'live' | 'test';
|
|
contactId?: string;
|
|
limit: string;
|
|
offset: string;
|
|
sortField?: 'issueDate';
|
|
sortOrder?: 'ascend' | 'descend';
|
|
}): Promise<GHLApiResponse<ListInvoicesResponseDto>> {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location' as const,
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.status && { status: params.status }),
|
|
...(params?.startAt && { startAt: params.startAt }),
|
|
...(params?.endAt && { endAt: params.endAt }),
|
|
...(params?.search && { search: params.search }),
|
|
...(params?.paymentMode && { paymentMode: params.paymentMode }),
|
|
...(params?.contactId && { contactId: params.contactId }),
|
|
...(params?.sortField && { sortField: params.sortField }),
|
|
...(params?.sortOrder && { sortOrder: params.sortOrder })
|
|
};
|
|
|
|
const response: AxiosResponse<ListInvoicesResponseDto> = await this.axiosInstance.get(
|
|
'/invoices/',
|
|
{ params: queryParams }
|
|
);
|
|
|
|
return this.wrapResponse(response.data);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|