5108 lines
169 KiB
JavaScript
5108 lines
169 KiB
JavaScript
/**
|
|
* GoHighLevel API Client
|
|
* Implements exact API endpoints from OpenAPI specifications v2021-07-28 (Contacts) and v2021-04-15 (Conversations)
|
|
*/
|
|
import axios from 'axios';
|
|
/**
|
|
* GoHighLevel API Client
|
|
* Handles all API communication with GHL services
|
|
*/
|
|
export class GHLApiClient {
|
|
axiosInstance;
|
|
config;
|
|
constructor(config) {
|
|
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) => {
|
|
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
|
|
*/
|
|
handleApiError(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
|
|
*/
|
|
wrapResponse(data) {
|
|
return {
|
|
success: true,
|
|
data
|
|
};
|
|
}
|
|
/**
|
|
* Create custom headers for different API versions
|
|
*/
|
|
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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...contactData,
|
|
locationId: contactData.locationId || this.config.locationId
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, updates) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
// Build minimal request body with only required/supported parameters
|
|
// Start with just locationId and pageLimit as per API requirements
|
|
const payload = {
|
|
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 = {};
|
|
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 = await this.axiosInstance.post('/contacts/search', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
const axiosError = error;
|
|
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, phone) {
|
|
try {
|
|
const params = {
|
|
locationId: this.config.locationId
|
|
};
|
|
if (email)
|
|
params.email = encodeURIComponent(email);
|
|
if (phone)
|
|
params.number = encodeURIComponent(phone);
|
|
const response = 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, tags) {
|
|
try {
|
|
const payload = { tags };
|
|
const response = 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, tags) {
|
|
try {
|
|
const payload = { tags };
|
|
const response = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const params = {
|
|
...searchParams,
|
|
locationId: searchParams.locationId || this.config.locationId
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...conversationData,
|
|
locationId: conversationData.locationId || this.config.locationId
|
|
};
|
|
const response = 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, updates) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...updates,
|
|
locationId: updates.locationId || this.config.locationId
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, options) {
|
|
try {
|
|
const params = {};
|
|
if (options?.lastMessageId)
|
|
params.lastMessageId = options.lastMessageId;
|
|
if (options?.limit)
|
|
params.limit = options.limit;
|
|
if (options?.type)
|
|
params.type = options.type;
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, message, fromNumber) {
|
|
try {
|
|
const messageData = {
|
|
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, subject, message, html, options) {
|
|
try {
|
|
const messageData = {
|
|
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) {
|
|
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 = 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) {
|
|
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 = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...postData,
|
|
locationId: postData.locationId || this.config.locationId
|
|
};
|
|
const response = 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, postData) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...postData,
|
|
locationId: postData.locationId || this.config.locationId
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
limit: params.limit,
|
|
offset: params.offset
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
limit: params.limit,
|
|
offset: params.offset
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
urlSlug: params.urlSlug,
|
|
...(params.postId && { postId: params.postId })
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, taskData) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, noteData) {
|
|
try {
|
|
const response = 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, taskId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/contacts/${contactId}/tasks/${taskId}`);
|
|
return this.wrapResponse(response.data.task);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update a task for a contact
|
|
* PUT /contacts/{contactId}/tasks/{taskId}
|
|
*/
|
|
async updateContactTask(contactId, taskId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/contacts/${contactId}/tasks/${taskId}`, updates);
|
|
return this.wrapResponse(response.data.task);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete a task for a contact
|
|
* DELETE /contacts/{contactId}/tasks/{taskId}
|
|
*/
|
|
async deleteContactTask(contactId, taskId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/tasks/${taskId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update task completion status
|
|
* PUT /contacts/{contactId}/tasks/{taskId}/completed
|
|
*/
|
|
async updateTaskCompletion(contactId, taskId, completed) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/contacts/${contactId}/tasks/${taskId}/completed`, { completed });
|
|
return this.wrapResponse(response.data.task);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get a specific note for a contact
|
|
* GET /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async getContactNote(contactId, noteId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/contacts/${contactId}/notes/${noteId}`);
|
|
return this.wrapResponse(response.data.note);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update a note for a contact
|
|
* PUT /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async updateContactNote(contactId, noteId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/contacts/${contactId}/notes/${noteId}`, updates);
|
|
return this.wrapResponse(response.data.note);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete a note for a contact
|
|
* DELETE /contacts/{contactId}/notes/{noteId}
|
|
*/
|
|
async deleteContactNote(contactId, noteId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/notes/${noteId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Upsert contact (create or update based on email/phone)
|
|
* POST /contacts/upsert
|
|
*/
|
|
async upsertContact(contactData) {
|
|
try {
|
|
const payload = {
|
|
...contactData,
|
|
locationId: contactData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/contacts/upsert', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get contacts by business ID
|
|
* GET /contacts/business/{businessId}
|
|
*/
|
|
async getContactsByBusiness(businessId, params = {}) {
|
|
try {
|
|
const queryParams = {
|
|
limit: params.limit || 25,
|
|
skip: params.skip || 0,
|
|
...(params.query && { query: params.query })
|
|
};
|
|
const response = await this.axiosInstance.get(`/contacts/business/${businessId}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get contact appointments
|
|
* GET /contacts/{contactId}/appointments
|
|
*/
|
|
async getContactAppointments(contactId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/contacts/${contactId}/appointments`);
|
|
return this.wrapResponse(response.data.events);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Bulk update contact tags
|
|
* POST /contacts/tags/bulk
|
|
*/
|
|
async bulkUpdateContactTags(contactIds, tags, operation, removeAllTags) {
|
|
try {
|
|
const payload = {
|
|
ids: contactIds,
|
|
tags,
|
|
operation,
|
|
...(removeAllTags !== undefined && { removeAllTags })
|
|
};
|
|
const response = await this.axiosInstance.post('/contacts/tags/bulk', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Bulk update contact business
|
|
* POST /contacts/business/bulk
|
|
*/
|
|
async bulkUpdateContactBusiness(contactIds, businessId) {
|
|
try {
|
|
const payload = {
|
|
ids: contactIds,
|
|
businessId: businessId || null
|
|
};
|
|
const response = await this.axiosInstance.post('/contacts/business/bulk', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add contact followers
|
|
* POST /contacts/{contactId}/followers
|
|
*/
|
|
async addContactFollowers(contactId, followers) {
|
|
try {
|
|
const payload = { followers };
|
|
const response = await this.axiosInstance.post(`/contacts/${contactId}/followers`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Remove contact followers
|
|
* DELETE /contacts/{contactId}/followers
|
|
*/
|
|
async removeContactFollowers(contactId, followers) {
|
|
try {
|
|
const payload = { followers };
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/followers`, { data: payload });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add contact to campaign
|
|
* POST /contacts/{contactId}/campaigns/{campaignId}
|
|
*/
|
|
async addContactToCampaign(contactId, campaignId) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/contacts/${contactId}/campaigns/${campaignId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Remove contact from campaign
|
|
* DELETE /contacts/{contactId}/campaigns/{campaignId}
|
|
*/
|
|
async removeContactFromCampaign(contactId, campaignId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/campaigns/${campaignId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Remove contact from all campaigns
|
|
* DELETE /contacts/{contactId}/campaigns
|
|
*/
|
|
async removeContactFromAllCampaigns(contactId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/campaigns`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add contact to workflow
|
|
* POST /contacts/{contactId}/workflow/{workflowId}
|
|
*/
|
|
async addContactToWorkflow(contactId, workflowId, eventStartTime) {
|
|
try {
|
|
const payload = eventStartTime ? { eventStartTime } : {};
|
|
const response = await this.axiosInstance.post(`/contacts/${contactId}/workflow/${workflowId}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Remove contact from workflow
|
|
* DELETE /contacts/{contactId}/workflow/{workflowId}
|
|
*/
|
|
async removeContactFromWorkflow(contactId, workflowId, eventStartTime) {
|
|
try {
|
|
const payload = eventStartTime ? { eventStartTime } : {};
|
|
const response = await this.axiosInstance.delete(`/contacts/${contactId}/workflow/${workflowId}`, { data: payload });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* UTILITY METHODS
|
|
*/
|
|
/**
|
|
* Test API connection and authentication
|
|
*/
|
|
async testConnection() {
|
|
try {
|
|
// Test with a simple GET request to check API connectivity
|
|
const response = 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) {
|
|
this.config.accessToken = newToken;
|
|
this.axiosInstance.defaults.headers['Authorization'] = `Bearer ${newToken}`;
|
|
process.stderr.write('[GHL API] Access token updated\n');
|
|
}
|
|
/**
|
|
* Get current configuration
|
|
*/
|
|
getConfig() {
|
|
return { ...this.config };
|
|
}
|
|
/**
|
|
* Generic request method for new endpoints
|
|
* Used by new tool modules that don't have specific client methods yet
|
|
*/
|
|
async makeRequest(method, path, body) {
|
|
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) {
|
|
try {
|
|
// Build query parameters with exact API naming (underscores)
|
|
const params = {
|
|
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 = await this.axiosInstance.get('/opportunities/search', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
const axiosError = error;
|
|
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) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get('/opportunities/pipelines', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get opportunity by ID
|
|
* GET /opportunities/{id}
|
|
*/
|
|
async getOpportunity(opportunityId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/opportunities/${opportunityId}`);
|
|
return this.wrapResponse(response.data.opportunity);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new opportunity
|
|
* POST /opportunities/
|
|
*/
|
|
async createOpportunity(opportunityData) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...opportunityData,
|
|
locationId: opportunityData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/opportunities/', payload);
|
|
return this.wrapResponse(response.data.opportunity);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update existing opportunity
|
|
* PUT /opportunities/{id}
|
|
*/
|
|
async updateOpportunity(opportunityId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/opportunities/${opportunityId}`, updates);
|
|
return this.wrapResponse(response.data.opportunity);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update opportunity status
|
|
* PUT /opportunities/{id}/status
|
|
*/
|
|
async updateOpportunityStatus(opportunityId, status) {
|
|
try {
|
|
const payload = { status };
|
|
const response = await this.axiosInstance.put(`/opportunities/${opportunityId}/status`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Upsert opportunity (create or update)
|
|
* POST /opportunities/upsert
|
|
*/
|
|
async upsertOpportunity(opportunityData) {
|
|
try {
|
|
// Ensure locationId is set
|
|
const payload = {
|
|
...opportunityData,
|
|
locationId: opportunityData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/opportunities/upsert', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete opportunity
|
|
* DELETE /opportunities/{id}
|
|
*/
|
|
async deleteOpportunity(opportunityId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/opportunities/${opportunityId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add followers to opportunity
|
|
* POST /opportunities/{id}/followers
|
|
*/
|
|
async addOpportunityFollowers(opportunityId, followers) {
|
|
try {
|
|
const payload = { followers };
|
|
const response = await this.axiosInstance.post(`/opportunities/${opportunityId}/followers`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Remove followers from opportunity
|
|
* DELETE /opportunities/{id}/followers
|
|
*/
|
|
async removeOpportunityFollowers(opportunityId, followers) {
|
|
try {
|
|
const payload = { followers };
|
|
const response = await this.axiosInstance.delete(`/opportunities/${opportunityId}/followers`, { data: payload });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* CALENDAR & APPOINTMENTS API METHODS
|
|
*/
|
|
/**
|
|
* Get all calendar groups in a location
|
|
* GET /calendars/groups
|
|
*/
|
|
async getCalendarGroups(locationId) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get('/calendars/groups', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new calendar group
|
|
* POST /calendars/groups
|
|
*/
|
|
async createCalendarGroup(groupData) {
|
|
try {
|
|
const payload = {
|
|
...groupData,
|
|
locationId: groupData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/calendars/groups', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get all calendars in a location
|
|
* GET /calendars/
|
|
*/
|
|
async getCalendars(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params?.locationId || this.config.locationId,
|
|
...(params?.groupId && { groupId: params.groupId }),
|
|
...(params?.showDrafted !== undefined && { showDrafted: params.showDrafted })
|
|
};
|
|
const response = await this.axiosInstance.get('/calendars/', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new calendar
|
|
* POST /calendars/
|
|
*/
|
|
async createCalendar(calendarData) {
|
|
try {
|
|
const payload = {
|
|
...calendarData,
|
|
locationId: calendarData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/calendars/', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get calendar by ID
|
|
* GET /calendars/{calendarId}
|
|
*/
|
|
async getCalendar(calendarId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/calendars/${calendarId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update calendar by ID
|
|
* PUT /calendars/{calendarId}
|
|
*/
|
|
async updateCalendar(calendarId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/${calendarId}`, updates);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete calendar by ID
|
|
* DELETE /calendars/{calendarId}
|
|
*/
|
|
async deleteCalendar(calendarId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/${calendarId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get calendar events/appointments
|
|
* GET /calendars/events
|
|
*/
|
|
async getCalendarEvents(eventParams) {
|
|
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 = await this.axiosInstance.get('/calendars/events', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get blocked slots
|
|
* GET /calendars/blocked-slots
|
|
*/
|
|
async getBlockedSlots(eventParams) {
|
|
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 = await this.axiosInstance.get('/calendars/blocked-slots', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get free slots for a calendar
|
|
* GET /calendars/{calendarId}/free-slots
|
|
*/
|
|
async getFreeSlots(slotParams) {
|
|
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 = await this.axiosInstance.get(`/calendars/${slotParams.calendarId}/free-slots`, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new appointment
|
|
* POST /calendars/events/appointments
|
|
*/
|
|
async createAppointment(appointmentData) {
|
|
try {
|
|
const payload = {
|
|
...appointmentData,
|
|
locationId: appointmentData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/calendars/events/appointments', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get appointment by ID
|
|
* GET /calendars/events/appointments/{eventId}
|
|
*/
|
|
async getAppointment(appointmentId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/calendars/events/appointments/${appointmentId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update appointment by ID
|
|
* PUT /calendars/events/appointments/{eventId}
|
|
*/
|
|
async updateAppointment(appointmentId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/events/appointments/${appointmentId}`, updates);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete appointment by ID
|
|
* DELETE /calendars/events/appointments/{eventId}
|
|
*/
|
|
async deleteAppointment(appointmentId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/events/appointments/${appointmentId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update block slot by ID
|
|
* PUT /calendars/events/block-slots/{eventId}
|
|
*/
|
|
async updateBlockSlot(blockSlotId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/events/block-slots/${blockSlotId}`, updates);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* EMAIL API METHODS
|
|
*/
|
|
async getEmailCampaigns(params) {
|
|
try {
|
|
const response = await this.axiosInstance.get('/emails/schedule', {
|
|
params: {
|
|
locationId: this.config.locationId,
|
|
...params
|
|
}
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
async createEmailTemplate(params) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/emails/builder', {
|
|
locationId: this.config.locationId,
|
|
type: 'html',
|
|
...params
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
async getEmailTemplates(params) {
|
|
try {
|
|
const response = await this.axiosInstance.get('/emails/builder', {
|
|
params: {
|
|
locationId: this.config.locationId,
|
|
...params
|
|
}
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
async updateEmailTemplate(params) {
|
|
try {
|
|
const { templateId, ...data } = params;
|
|
const response = 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);
|
|
}
|
|
}
|
|
async deleteEmailTemplate(params) {
|
|
try {
|
|
const { templateId } = params;
|
|
const response = await this.axiosInstance.delete(`/emails/builder/${this.config.locationId}/${templateId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* LOCATION API METHODS
|
|
*/
|
|
/**
|
|
* Search locations/sub-accounts
|
|
* GET /locations/search
|
|
*/
|
|
async searchLocations(params = {}) {
|
|
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 = await this.axiosInstance.get('/locations/search', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get location by ID
|
|
* GET /locations/{locationId}
|
|
*/
|
|
async getLocationById(locationId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new location/sub-account
|
|
* POST /locations/
|
|
*/
|
|
async createLocation(locationData) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/locations/', locationData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update location/sub-account
|
|
* PUT /locations/{locationId}
|
|
*/
|
|
async updateLocation(locationId, updates) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/locations/${locationId}`, updates);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete location/sub-account
|
|
* DELETE /locations/{locationId}
|
|
*/
|
|
async deleteLocation(locationId, deleteTwilioAccount) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/locations/${locationId}`, {
|
|
params: { deleteTwilioAccount }
|
|
});
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* LOCATION TAGS API METHODS
|
|
*/
|
|
/**
|
|
* Get location tags
|
|
* GET /locations/{locationId}/tags
|
|
*/
|
|
async getLocationTags(locationId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/tags`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create location tag
|
|
* POST /locations/{locationId}/tags
|
|
*/
|
|
async createLocationTag(locationId, tagData) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/locations/${locationId}/tags`, tagData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get location tag by ID
|
|
* GET /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async getLocationTag(locationId, tagId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/tags/${tagId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update location tag
|
|
* PUT /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async updateLocationTag(locationId, tagId, tagData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/locations/${locationId}/tags/${tagId}`, tagData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete location tag
|
|
* DELETE /locations/{locationId}/tags/{tagId}
|
|
*/
|
|
async deleteLocationTag(locationId, tagId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/locations/${locationId}/tags/${tagId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* LOCATION TASKS API METHODS
|
|
*/
|
|
/**
|
|
* Search location tasks
|
|
* POST /locations/{locationId}/tasks/search
|
|
*/
|
|
async searchLocationTasks(locationId, searchParams) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/locations/${locationId}/tasks/search`, searchParams);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* CUSTOM FIELDS API METHODS
|
|
*/
|
|
/**
|
|
* Get custom fields for location
|
|
* GET /locations/{locationId}/customFields
|
|
*/
|
|
async getLocationCustomFields(locationId, model) {
|
|
try {
|
|
const params = {};
|
|
if (model)
|
|
params.model = model;
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/customFields`, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create custom field for location
|
|
* POST /locations/{locationId}/customFields
|
|
*/
|
|
async createLocationCustomField(locationId, fieldData) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/locations/${locationId}/customFields`, fieldData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get custom field by ID
|
|
* GET /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async getLocationCustomField(locationId, customFieldId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/customFields/${customFieldId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update custom field
|
|
* PUT /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async updateLocationCustomField(locationId, customFieldId, fieldData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/locations/${locationId}/customFields/${customFieldId}`, fieldData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete custom field
|
|
* DELETE /locations/{locationId}/customFields/{id}
|
|
*/
|
|
async deleteLocationCustomField(locationId, customFieldId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/locations/${locationId}/customFields/${customFieldId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Upload file to custom fields
|
|
* POST /locations/{locationId}/customFields/upload
|
|
*/
|
|
async uploadLocationCustomFieldFile(locationId, uploadData) {
|
|
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 = 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);
|
|
}
|
|
}
|
|
/**
|
|
* CUSTOM VALUES API METHODS
|
|
*/
|
|
/**
|
|
* Get custom values for location
|
|
* GET /locations/{locationId}/customValues
|
|
*/
|
|
async getLocationCustomValues(locationId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/customValues`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create custom value for location
|
|
* POST /locations/{locationId}/customValues
|
|
*/
|
|
async createLocationCustomValue(locationId, valueData) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/locations/${locationId}/customValues`, valueData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get custom value by ID
|
|
* GET /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async getLocationCustomValue(locationId, customValueId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/locations/${locationId}/customValues/${customValueId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update custom value
|
|
* PUT /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async updateLocationCustomValue(locationId, customValueId, valueData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/locations/${locationId}/customValues/${customValueId}`, valueData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete custom value
|
|
* DELETE /locations/{locationId}/customValues/{id}
|
|
*/
|
|
async deleteLocationCustomValue(locationId, customValueId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/locations/${locationId}/customValues/${customValueId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* TEMPLATES API METHODS
|
|
*/
|
|
/**
|
|
* Get location templates (SMS/Email)
|
|
* GET /locations/{locationId}/templates
|
|
*/
|
|
async getLocationTemplates(locationId, params) {
|
|
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 = await this.axiosInstance.get(`/locations/${locationId}/templates`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete location template
|
|
* DELETE /locations/{locationId}/templates/{id}
|
|
*/
|
|
async deleteLocationTemplate(locationId, templateId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/locations/${locationId}/templates/${templateId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* TIMEZONES API METHODS
|
|
*/
|
|
/**
|
|
* Get available timezones
|
|
* GET /locations/{locationId}/timezones
|
|
*/
|
|
async getTimezones(locationId) {
|
|
try {
|
|
const endpoint = locationId ? `/locations/${locationId}/timezones` : '/locations/timezones';
|
|
const response = await this.axiosInstance.get(endpoint);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* EMAIL ISV (VERIFICATION) API METHODS
|
|
*/
|
|
/**
|
|
* Verify email address or contact
|
|
* POST /email/verify
|
|
*/
|
|
async verifyEmail(locationId, verificationData) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/email/verify', verificationData, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* ADDITIONAL CONVERSATION/MESSAGE API METHODS
|
|
*/
|
|
/**
|
|
* Get email message by ID
|
|
* GET /conversations/messages/email/{id}
|
|
*/
|
|
async getEmailMessage(emailMessageId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/conversations/messages/email/${emailMessageId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Cancel scheduled email message
|
|
* DELETE /conversations/messages/email/{emailMessageId}/schedule
|
|
*/
|
|
async cancelScheduledEmail(emailMessageId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/conversations/messages/email/${emailMessageId}/schedule`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add inbound message manually
|
|
* POST /conversations/messages/inbound
|
|
*/
|
|
async addInboundMessage(messageData) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/conversations/messages/inbound', messageData, { headers: this.getConversationHeaders() });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Add outbound call manually
|
|
* POST /conversations/messages/outbound
|
|
*/
|
|
async addOutboundCall(messageData) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/conversations/messages/outbound', messageData, { headers: this.getConversationHeaders() });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Cancel scheduled message
|
|
* DELETE /conversations/messages/{messageId}/schedule
|
|
*/
|
|
async cancelScheduledMessage(messageId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/conversations/messages/${messageId}/schedule`, { headers: this.getConversationHeaders() });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Upload file attachments for messages
|
|
* POST /conversations/messages/upload
|
|
*/
|
|
async uploadMessageAttachments(uploadData) {
|
|
try {
|
|
const response = 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);
|
|
}
|
|
}
|
|
/**
|
|
* Update message status
|
|
* PUT /conversations/messages/{messageId}/status
|
|
*/
|
|
async updateMessageStatus(messageId, statusData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/conversations/messages/${messageId}/status`, statusData, { headers: this.getConversationHeaders() });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get message recording
|
|
* GET /conversations/messages/{messageId}/locations/{locationId}/recording
|
|
*/
|
|
async getMessageRecording(messageId, locationId) {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response = await this.axiosInstance.get(`/conversations/messages/${messageId}/locations/${locId}/recording`, {
|
|
headers: this.getConversationHeaders(),
|
|
responseType: 'arraybuffer'
|
|
});
|
|
const recordingResponse = {
|
|
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);
|
|
}
|
|
}
|
|
/**
|
|
* Get message transcription
|
|
* GET /conversations/locations/{locationId}/messages/{messageId}/transcription
|
|
*/
|
|
async getMessageTranscription(messageId, locationId) {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response = 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);
|
|
}
|
|
}
|
|
/**
|
|
* Download message transcription
|
|
* GET /conversations/locations/{locationId}/messages/{messageId}/transcription/download
|
|
*/
|
|
async downloadMessageTranscription(messageId, locationId) {
|
|
try {
|
|
const locId = locationId || this.config.locationId;
|
|
const response = 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);
|
|
}
|
|
}
|
|
/**
|
|
* Live chat typing indicator
|
|
* POST /conversations/providers/live-chat/typing
|
|
*/
|
|
async liveChatTyping(typingData) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/conversations/providers/live-chat/typing', typingData, { headers: this.getConversationHeaders() });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ============================================================================
|
|
// SOCIAL MEDIA POSTING API METHODS
|
|
// ============================================================================
|
|
// ===== POST MANAGEMENT =====
|
|
/**
|
|
* Search/List Social Media Posts
|
|
*/
|
|
async searchSocialPosts(searchData) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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, updateData) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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() {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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, companyId, userId) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params = {};
|
|
if (companyId)
|
|
params.companyId = companyId;
|
|
if (userId)
|
|
params.userId = userId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
// Note: This would typically use FormData for file upload
|
|
const response = 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, limit, includeUsers, userId) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params = {};
|
|
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 = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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, skip, limit) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const params = {};
|
|
if (skip !== undefined)
|
|
params.skip = skip.toString();
|
|
if (limit !== undefined)
|
|
params.limit = limit.toString();
|
|
const response = 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, finalizeData) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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, postId) {
|
|
try {
|
|
const locationId = this.config.locationId;
|
|
const response = 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, limit, skip) {
|
|
// TODO: Implement this method properly
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
// TODO: Implement remaining social media API methods
|
|
async getSocialCategory(categoryId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getSocialTags(searchText, limit, skip) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getSocialTagsByIds(tagData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async startSocialOAuth(platform, userId, page, reconnect) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getGoogleBusinessLocations(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async setGoogleBusinessLocations(accountId, locationData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getFacebookPages(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async attachFacebookPages(accountId, pageData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getInstagramAccounts(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async attachInstagramAccounts(accountId, accountData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getLinkedInAccounts(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async attachLinkedInAccounts(accountId, accountData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getTwitterProfile(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async attachTwitterProfile(accountId, profileData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getTikTokProfile(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async attachTikTokProfile(accountId, profileData) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
async getTikTokBusinessProfile(accountId) {
|
|
throw new Error('Method not yet implemented');
|
|
}
|
|
// ===== MISSING CALENDAR GROUPS MANAGEMENT METHODS =====
|
|
/**
|
|
* Validate calendar group slug
|
|
* GET /calendars/groups/slug/validate
|
|
*/
|
|
async validateCalendarGroupSlug(slug, locationId) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId,
|
|
slug
|
|
};
|
|
const response = await this.axiosInstance.get('/calendars/groups/slug/validate', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update calendar group by ID
|
|
* PUT /calendars/groups/{groupId}
|
|
*/
|
|
async updateCalendarGroup(groupId, updateData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/groups/${groupId}`, updateData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete calendar group by ID
|
|
* DELETE /calendars/groups/{groupId}
|
|
*/
|
|
async deleteCalendarGroup(groupId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/groups/${groupId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Disable calendar group
|
|
* POST /calendars/groups/{groupId}/status
|
|
*/
|
|
async disableCalendarGroup(groupId, isActive) {
|
|
try {
|
|
const payload = { isActive };
|
|
const response = await this.axiosInstance.post(`/calendars/groups/${groupId}/status`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== APPOINTMENT NOTES METHODS =====
|
|
/**
|
|
* Get appointment notes
|
|
* GET /calendars/events/appointments/{appointmentId}/notes
|
|
*/
|
|
async getAppointmentNotes(appointmentId, limit = 10, offset = 0) {
|
|
try {
|
|
const params = { limit, offset };
|
|
const response = await this.axiosInstance.get(`/calendars/events/appointments/${appointmentId}/notes`, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create appointment note
|
|
* POST /calendars/events/appointments/{appointmentId}/notes
|
|
*/
|
|
async createAppointmentNote(appointmentId, noteData) {
|
|
try {
|
|
const response = await this.axiosInstance.post(`/calendars/events/appointments/${appointmentId}/notes`, noteData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update appointment note
|
|
* PUT /calendars/events/appointments/{appointmentId}/notes/{noteId}
|
|
*/
|
|
async updateAppointmentNote(appointmentId, noteId, updateData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/events/appointments/${appointmentId}/notes/${noteId}`, updateData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete appointment note
|
|
* DELETE /calendars/events/appointments/{appointmentId}/notes/{noteId}
|
|
*/
|
|
async deleteAppointmentNote(appointmentId, noteId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/events/appointments/${appointmentId}/notes/${noteId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== CALENDAR RESOURCES METHODS =====
|
|
/**
|
|
* Get calendar resources
|
|
* GET /calendars/resources/{resourceType}
|
|
*/
|
|
async getCalendarResources(resourceType, limit = 20, skip = 0, locationId) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId,
|
|
limit,
|
|
skip
|
|
};
|
|
const response = await this.axiosInstance.get(`/calendars/resources/${resourceType}`, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create calendar resource
|
|
* POST /calendars/resources/{resourceType}
|
|
*/
|
|
async createCalendarResource(resourceType, resourceData) {
|
|
try {
|
|
const payload = {
|
|
...resourceData,
|
|
locationId: resourceData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post(`/calendars/resources/${resourceType}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get calendar resource by ID
|
|
* GET /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async getCalendarResource(resourceType, resourceId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/calendars/resources/${resourceType}/${resourceId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update calendar resource
|
|
* PUT /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async updateCalendarResource(resourceType, resourceId, updateData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/resources/${resourceType}/${resourceId}`, updateData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete calendar resource
|
|
* DELETE /calendars/resources/{resourceType}/{resourceId}
|
|
*/
|
|
async deleteCalendarResource(resourceType, resourceId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/resources/${resourceType}/${resourceId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== CALENDAR NOTIFICATIONS METHODS =====
|
|
/**
|
|
* Get calendar notifications
|
|
* GET /calendars/{calendarId}/notifications
|
|
*/
|
|
async getCalendarNotifications(calendarId, queryParams) {
|
|
try {
|
|
const params = {
|
|
...queryParams
|
|
};
|
|
const response = await this.axiosInstance.get(`/calendars/${calendarId}/notifications`, { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create calendar notifications
|
|
* POST /calendars/{calendarId}/notifications
|
|
*/
|
|
async createCalendarNotifications(calendarId, notifications) {
|
|
try {
|
|
const payload = { notifications };
|
|
const response = await this.axiosInstance.post(`/calendars/${calendarId}/notifications`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get calendar notification by ID
|
|
* GET /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async getCalendarNotification(calendarId, notificationId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/calendars/${calendarId}/notifications/${notificationId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update calendar notification
|
|
* PUT /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async updateCalendarNotification(calendarId, notificationId, updateData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/calendars/${calendarId}/notifications/${notificationId}`, updateData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete calendar notification
|
|
* DELETE /calendars/{calendarId}/notifications/{notificationId}
|
|
*/
|
|
async deleteCalendarNotification(calendarId, notificationId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/calendars/${calendarId}/notifications/${notificationId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get blocked slots by location
|
|
* GET /calendars/blocked-slots
|
|
*/
|
|
async getBlockedSlotsByLocation(slotParams) {
|
|
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 = await this.axiosInstance.get(`/calendars/blocked-slots?${params}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create a new block slot
|
|
* POST /calendars/blocked-slots
|
|
*/
|
|
async createBlockSlot(blockSlotData) {
|
|
try {
|
|
const payload = {
|
|
...blockSlotData,
|
|
locationId: blockSlotData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/calendars/blocked-slots', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== MEDIA LIBRARY API METHODS =====
|
|
/**
|
|
* Get list of files and folders from media library
|
|
* GET /medias/files
|
|
*/
|
|
async getMediaFiles(params) {
|
|
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 = await this.axiosInstance.get(`/medias/files?${queryParams}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Upload file to media library
|
|
* POST /medias/upload-file
|
|
*/
|
|
async uploadMediaFile(uploadData) {
|
|
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 = 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);
|
|
}
|
|
}
|
|
/**
|
|
* Delete file or folder from media library
|
|
* DELETE /medias/{id}
|
|
*/
|
|
async deleteMediaFile(deleteParams) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altType: deleteParams.altType,
|
|
altId: deleteParams.altId
|
|
});
|
|
const response = await this.axiosInstance.delete(`/medias/${deleteParams.id}?${queryParams}`);
|
|
return this.wrapResponse({ success: true, message: 'Media file deleted successfully' });
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== CUSTOM OBJECTS API METHODS =====
|
|
/**
|
|
* Get all objects for a location
|
|
* GET /objects/
|
|
*/
|
|
async getObjectsByLocation(locationId) {
|
|
try {
|
|
const params = {
|
|
locationId: locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get('/objects/', { params });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create custom object schema
|
|
* POST /objects/
|
|
*/
|
|
async createObjectSchema(schemaData) {
|
|
try {
|
|
const payload = {
|
|
...schemaData,
|
|
locationId: schemaData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/objects/', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get object schema by key/id
|
|
* GET /objects/{key}
|
|
*/
|
|
async getObjectSchema(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
...(params.fetchProperties !== undefined && { fetchProperties: params.fetchProperties.toString() })
|
|
};
|
|
const response = await this.axiosInstance.get(`/objects/${params.key}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update object schema by key/id
|
|
* PUT /objects/{key}
|
|
*/
|
|
async updateObjectSchema(key, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.put(`/objects/${key}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create object record
|
|
* POST /objects/{schemaKey}/records
|
|
*/
|
|
async createObjectRecord(schemaKey, recordData) {
|
|
try {
|
|
const payload = {
|
|
...recordData,
|
|
locationId: recordData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post(`/objects/${schemaKey}/records`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get object record by id
|
|
* GET /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async getObjectRecord(schemaKey, recordId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/objects/${schemaKey}/records/${recordId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update object record
|
|
* PUT /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async updateObjectRecord(schemaKey, recordId, updateData) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.put(`/objects/${schemaKey}/records/${recordId}`, updateData, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete object record
|
|
* DELETE /objects/{schemaKey}/records/{id}
|
|
*/
|
|
async deleteObjectRecord(schemaKey, recordId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/objects/${schemaKey}/records/${recordId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Search object records
|
|
* POST /objects/{schemaKey}/records/search
|
|
*/
|
|
async searchObjectRecords(schemaKey, searchData) {
|
|
try {
|
|
const payload = {
|
|
...searchData,
|
|
locationId: searchData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post(`/objects/${schemaKey}/records/search`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== ASSOCIATIONS API METHODS =====
|
|
/**
|
|
* Get all associations for a location
|
|
* GET /associations/
|
|
*/
|
|
async getAssociations(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
skip: params.skip.toString(),
|
|
limit: params.limit.toString()
|
|
};
|
|
const response = await this.axiosInstance.get('/associations/', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create association
|
|
* POST /associations/
|
|
*/
|
|
async createAssociation(associationData) {
|
|
try {
|
|
const payload = {
|
|
...associationData,
|
|
locationId: associationData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/associations/', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get association by ID
|
|
* GET /associations/{associationId}
|
|
*/
|
|
async getAssociationById(associationId) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/associations/${associationId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update association
|
|
* PUT /associations/{associationId}
|
|
*/
|
|
async updateAssociation(associationId, updateData) {
|
|
try {
|
|
const response = await this.axiosInstance.put(`/associations/${associationId}`, updateData);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete association
|
|
* DELETE /associations/{associationId}
|
|
*/
|
|
async deleteAssociation(associationId) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/associations/${associationId}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get association by key name
|
|
* GET /associations/key/{key_name}
|
|
*/
|
|
async getAssociationByKey(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get(`/associations/key/${params.keyName}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get association by object key
|
|
* GET /associations/objectKey/{objectKey}
|
|
*/
|
|
async getAssociationByObjectKey(params) {
|
|
try {
|
|
const queryParams = params.locationId ? {
|
|
locationId: params.locationId
|
|
} : {};
|
|
const response = await this.axiosInstance.get(`/associations/objectKey/${params.objectKey}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create relation between entities
|
|
* POST /associations/relations
|
|
*/
|
|
async createRelation(relationData) {
|
|
try {
|
|
const payload = {
|
|
...relationData,
|
|
locationId: relationData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/associations/relations', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get relations by record ID
|
|
* GET /associations/relations/{recordId}
|
|
*/
|
|
async getRelationsByRecord(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId,
|
|
skip: params.skip.toString(),
|
|
limit: params.limit.toString(),
|
|
...(params.associationIds && { associationIds: params.associationIds })
|
|
};
|
|
const response = await this.axiosInstance.get(`/associations/relations/${params.recordId}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete relation
|
|
* DELETE /associations/relations/{relationId}
|
|
*/
|
|
async deleteRelation(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.delete(`/associations/relations/${params.relationId}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== CUSTOM FIELDS V2 API METHODS =====
|
|
/**
|
|
* Get custom field or folder by ID
|
|
* GET /custom-fields/{id}
|
|
*/
|
|
async getCustomFieldV2ById(id) {
|
|
try {
|
|
const response = await this.axiosInstance.get(`/custom-fields/${id}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create custom field
|
|
* POST /custom-fields/
|
|
*/
|
|
async createCustomFieldV2(fieldData) {
|
|
try {
|
|
const payload = {
|
|
...fieldData,
|
|
locationId: fieldData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/custom-fields/', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update custom field by ID
|
|
* PUT /custom-fields/{id}
|
|
*/
|
|
async updateCustomFieldV2(id, fieldData) {
|
|
try {
|
|
const payload = {
|
|
...fieldData,
|
|
locationId: fieldData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.put(`/custom-fields/${id}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete custom field by ID
|
|
* DELETE /custom-fields/{id}
|
|
*/
|
|
async deleteCustomFieldV2(id) {
|
|
try {
|
|
const response = await this.axiosInstance.delete(`/custom-fields/${id}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get custom fields by object key
|
|
* GET /custom-fields/object-key/{objectKey}
|
|
*/
|
|
async getCustomFieldsV2ByObjectKey(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get(`/custom-fields/object-key/${params.objectKey}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Create custom field folder
|
|
* POST /custom-fields/folder
|
|
*/
|
|
async createCustomFieldV2Folder(folderData) {
|
|
try {
|
|
const payload = {
|
|
...folderData,
|
|
locationId: folderData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.post('/custom-fields/folder', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Update custom field folder name
|
|
* PUT /custom-fields/folder/{id}
|
|
*/
|
|
async updateCustomFieldV2Folder(id, folderData) {
|
|
try {
|
|
const payload = {
|
|
...folderData,
|
|
locationId: folderData.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.put(`/custom-fields/folder/${id}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Delete custom field folder
|
|
* DELETE /custom-fields/folder/{id}
|
|
*/
|
|
async deleteCustomFieldV2Folder(params) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: params.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.delete(`/custom-fields/folder/${params.id}`, { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== WORKFLOWS API METHODS =====
|
|
/**
|
|
* Get all workflows for a location
|
|
* GET /workflows/
|
|
*/
|
|
async getWorkflows(request) {
|
|
try {
|
|
const queryParams = {
|
|
locationId: request.locationId || this.config.locationId
|
|
};
|
|
const response = await this.axiosInstance.get('/workflows/', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
// ===== SURVEYS API METHODS =====
|
|
/**
|
|
* Get all surveys for a location
|
|
* GET /surveys/
|
|
*/
|
|
async getSurveys(request) {
|
|
try {
|
|
const queryParams = {
|
|
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 = await this.axiosInstance.get('/surveys/', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw this.handleApiError(error);
|
|
}
|
|
}
|
|
/**
|
|
* Get survey submissions with filtering and pagination
|
|
* GET /surveys/submissions
|
|
*/
|
|
async getSurveySubmissions(request) {
|
|
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 = 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) {
|
|
try {
|
|
const payload = {
|
|
...zoneData,
|
|
altId: zoneData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
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 = 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, params) {
|
|
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 = 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, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...rateData,
|
|
altId: rateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, rateData) {
|
|
try {
|
|
const payload = {
|
|
...rateData,
|
|
altId: rateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
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 = 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, shippingRateId, params) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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, shippingRateId, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, shippingRateId, params) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...carrierData,
|
|
altId: carrierData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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, params) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...settingData,
|
|
altId: settingData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const altId = params.altId || this.config.locationId;
|
|
const queryParams = new URLSearchParams({
|
|
altId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, updateData) {
|
|
try {
|
|
const response = 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, locationId) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
const response = await this.axiosInstance.get(`/products/${productId}?${queryParams.toString()}`);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* List products
|
|
* GET /products/
|
|
*/
|
|
async listProducts(params) {
|
|
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 = 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, locationId) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, priceData) {
|
|
try {
|
|
const payload = {
|
|
...priceData,
|
|
locationId: priceData.locationId || this.config.locationId
|
|
};
|
|
const response = 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, priceId, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
locationId: updateData.locationId || this.config.locationId
|
|
};
|
|
const response = 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, priceId, locationId) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
const response = 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, params) {
|
|
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 = 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, priceId, locationId) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
locationId: locationId || this.config.locationId
|
|
});
|
|
const response = 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) {
|
|
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 = 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) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
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 = 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, updateData) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...collectionData,
|
|
altId: collectionData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
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 = 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, params) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location'
|
|
});
|
|
const response = 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) {
|
|
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 = 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) {
|
|
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 = 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, updateData) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const queryParams = new URLSearchParams({
|
|
altId: params.altId || this.config.locationId,
|
|
altType: 'location',
|
|
productId: params.productId
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...updateData,
|
|
altId: updateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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, params) {
|
|
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 = 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, data) {
|
|
try {
|
|
const response = 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, params) {
|
|
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 = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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, params) {
|
|
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 = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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, params) {
|
|
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 = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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) {
|
|
try {
|
|
const response = await this.axiosInstance.post('/payments/coupon', data);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Update coupon
|
|
* PUT /payments/coupon
|
|
*/
|
|
async updateCoupon(data) {
|
|
try {
|
|
const response = await this.axiosInstance.put('/payments/coupon', data);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Delete coupon
|
|
* DELETE /payments/coupon
|
|
*/
|
|
async deleteCoupon(data) {
|
|
try {
|
|
const response = await this.axiosInstance.delete('/payments/coupon', { data });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Get coupon
|
|
* GET /payments/coupon
|
|
*/
|
|
async getCoupon(params) {
|
|
try {
|
|
const queryParams = new URLSearchParams();
|
|
Object.entries(params).forEach(([key, value]) => {
|
|
if (value !== undefined && value !== null) {
|
|
queryParams.append(key, value.toString());
|
|
}
|
|
});
|
|
const response = 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, data) {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
const response = 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, data) {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
const response = 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, data) {
|
|
try {
|
|
const queryParams = new URLSearchParams({ locationId });
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
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 = 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, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, templateData) {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, configData) {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, configData) {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
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 = 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, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, scheduleData) {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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, scheduleData) {
|
|
try {
|
|
const payload = {
|
|
...scheduleData,
|
|
altId: scheduleData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, paymentData) {
|
|
try {
|
|
const payload = {
|
|
...paymentData,
|
|
altId: paymentData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, cancelData) {
|
|
try {
|
|
const payload = {
|
|
...cancelData,
|
|
altId: cancelData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, invoiceData) {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = await this.axiosInstance.put(`/invoices/${invoiceId}`, payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* Delete invoice
|
|
* DELETE /invoices/{invoiceId}
|
|
*/
|
|
async deleteInvoice(invoiceId, params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, configData) {
|
|
try {
|
|
const payload = {
|
|
...configData,
|
|
altId: configData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, voidData) {
|
|
try {
|
|
const payload = {
|
|
...voidData,
|
|
altId: voidData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, sendData) {
|
|
try {
|
|
const payload = {
|
|
...sendData,
|
|
altId: sendData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, paymentData) {
|
|
try {
|
|
const payload = {
|
|
...paymentData,
|
|
altId: paymentData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...estimateData,
|
|
altId: estimateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, estimateData) {
|
|
try {
|
|
const payload = {
|
|
...estimateData,
|
|
altId: estimateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, deleteData) {
|
|
try {
|
|
const payload = {
|
|
...deleteData,
|
|
altId: deleteData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, sendData) {
|
|
try {
|
|
const payload = {
|
|
...sendData,
|
|
altId: sendData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, invoiceData) {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
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 = 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) {
|
|
try {
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
limit: params?.limit || '10',
|
|
offset: params?.offset || '0',
|
|
...(params?.search && { search: params.search })
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, templateData) {
|
|
try {
|
|
const payload = {
|
|
...templateData,
|
|
altId: templateData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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, deleteData) {
|
|
try {
|
|
const payload = {
|
|
...deleteData,
|
|
altId: deleteData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
templateId: params?.templateId || ''
|
|
};
|
|
const response = 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) {
|
|
try {
|
|
const payload = {
|
|
...invoiceData,
|
|
altId: invoiceData.altId || this.config.locationId,
|
|
altType: 'location'
|
|
};
|
|
const response = await this.axiosInstance.post('/invoices/', payload);
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* List invoices
|
|
* GET /invoices/
|
|
*/
|
|
async listInvoices(params) {
|
|
try {
|
|
const queryParams = {
|
|
altId: params?.altId || this.config.locationId,
|
|
altType: 'location',
|
|
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 = await this.axiosInstance.get('/invoices/', { params: queryParams });
|
|
return this.wrapResponse(response.data);
|
|
}
|
|
catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|