API INTEGRATION PATTERNS
Airbnb Admin Panel
This document provides comprehensive information about API integration patterns used in the Airbnb Admin Panel, including HTTP client configuration, request/response handling, error management, and performance optimization strategies.
Architectural Design Credit and Contact Information
The architectural design of this API integration system is credited to Mindbricks Genesis Engine.
We encourage open communication and welcome any questions or discussions related to the architectural aspects of this API integration system.
Documentation Scope
This guide covers the complete API integration patterns within the Airbnb Admin Panel. It includes HTTP client configuration, request/response handling, error management, caching strategies, and performance optimization techniques.
Intended Audience
This documentation is intended for frontend developers, API integrators, and system architects who need to understand, implement, or maintain API integration patterns within the admin panel.
HTTP Client Architecture
Service-Specific Axios Instances
Messaging Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const messagingAxiosInstance = axios.create({
baseURL: CONFIG.messagingServiceUrl
});
messagingAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default messagingAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await messagingAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const messagingEndpoints = {
messageThread: {
createMessageThread: '/v1/messagethreads'
,
updateMessageThread: '/v1/messagethreads/:messageThreadId'
,
deleteMessageThread: '/v1/messagethreads/:messageThreadId'
,
getMessageThread: '/v1/messagethreads/:messageThreadId'
,
listMessageThreads: '/v1/messagethreads'
},
messageReport: {
listMessageReports: '/v1/messagereports'
,
createMessageReport: '/v1/messagereports'
,
updateMessageReport: '/v1/messagereports/:messageReportId'
,
getMessageReport: '/v1/messagereports/:messageReportId'
},
message: {
deleteMessage: '/v1/messages/:messageId'
,
updateMessage: '/v1/messages/:messageId'
,
createMessage: '/v1/messages'
,
getMessage: '/v1/messages/:messageId'
,
getThreadMessages: '/v1/threadmessages/:threadId'
,
gotthreadMessages: '/v1/gotthreadmessages/:threadId'
}
};
PropertyCatalog Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const propertyCatalogAxiosInstance = axios.create({
baseURL: CONFIG.propertyCatalogServiceUrl
});
propertyCatalogAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default propertyCatalogAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await propertyCatalogAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const propertyCatalogEndpoints = {
listingCalendar: {
updateListingCalendar: '/v1/listingcalendars/:listingCalendarId'
,
createListingCalendar: '/v1/listingcalendars'
,
deleteListingCalendar: '/v1/listingcalendars/:listingCalendarId'
,
getListingCalendar: '/v1/listingcalendars/:listingCalendarId'
,
listListingCalendars: '/v1/listingcalendars'
},
listingAmenity: {
listListingAmenities: '/v1/listingamenities'
,
updateListingAmenity: '/v1/listingamenities/:listingAmenityId'
,
getListingAmenity: '/v1/listingamenities/:listingAmenityId'
,
createListingAmenity: '/v1/listingamenities'
,
deleteListingAmenity: '/v1/listingamenities/:listingAmenityId'
},
listing: {
updateListing: '/v1/listings/:listingId'
,
createListing: '/v1/listings'
,
deleteListing: '/v1/listings/:listingId'
,
listListings: '/v1/listings'
,
getListing: '/v1/listings/:listingId'
},
listingLocaleText: {
createListingLocaleText: '/v1/listinglocaletexts'
,
deleteListingLocaleText: '/v1/listinglocaletexts/:listingLocaleTextId'
,
listListingLocaleTexts: '/v1/listinglocaletexts'
,
updateListingLocaleText: '/v1/listinglocaletexts/:listingLocaleTextId'
,
getListingLocaleText: '/v1/listinglocaletexts/:listingLocaleTextId'
}
};
AdminPanel Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const adminPanelAxiosInstance = axios.create({
baseURL: CONFIG.adminPanelServiceUrl
});
adminPanelAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default adminPanelAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await adminPanelAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const adminPanelEndpoints = {
localizationSetting: {
createLocalizationSetting: '/v1/localizationsettings'
,
updateLocalizationSetting: '/v1/localizationsettings/:localizationSettingId'
,
listLocalizationSettings: '/v1/localizationsettings'
},
adminDisputeAction: {
listAdminDisputeActions: '/v1/admindisputeactions'
,
createAdminDisputeAction: '/v1/admindisputeactions'
},
apiKey: {
createApiKey: '/v1/apikeys'
,
listApiKeys: '/v1/apikeys'
,
updateApiKey: '/v1/apikeys/:apiKeyId'
},
financialReport: {
getFinancialReport: '/v1/financialreports/:financialReportId'
,
createFinancialReport: '/v1/financialreports'
,
listFinancialReports: '/v1/financialreports'
},
auditLog: {
getAuditLog: '/v1/auditlogs/:auditLogId'
,
listAuditLogs: '/v1/auditlogs'
,
createAuditLog: '/v1/auditlogs'
},
gdprAction: {
updateGdprAction: '/v1/gdpractions/:gdprActionId'
,
listGdprActions: '/v1/gdpractions'
,
createGdprAction: '/v1/gdpractions'
}
};
BookingManagement Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const bookingManagementAxiosInstance = axios.create({
baseURL: CONFIG.bookingManagementServiceUrl
});
bookingManagementAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default bookingManagementAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await bookingManagementAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const bookingManagementEndpoints = {
reservation: {
getReservation: '/v1/reservations/:reservationId'
,
listReservations: '/v1/reservations'
,
createReservation: '/v1/reservations'
,
deleteReservation: '/v1/reservations/:reservationId'
,
updateReservation: '/v1/reservations/:reservationId'
,
startReservationPayment: '/v1/startreservationpayment/:reservationId'
,
refreshReservationPayment: '/v1/refreshreservationpayment/:reservationId'
,
callbackReservationPayment: '/v1/callbackreservationpayment'
},
paymentRecord: {
getPaymentRecord: '/v1/paymentrecords/:paymentRecordId'
,
createPaymentRecord: '/v1/paymentrecords'
,
listPaymentRecords: '/v1/paymentrecords'
},
dispute: {
updateDispute: '/v1/disputes/:disputeId'
,
createDispute: '/v1/disputes'
,
listDisputes: '/v1/disputes'
,
getDispute: '/v1/disputes/:disputeId'
},
sys_reservationPayment: {
getReservationPayment2: '/v1/reservationpayment2/:sys_reservationPaymentId'
,
listReservationPayments2: '/v1/reservationpayments2'
,
createReservationPayment: '/v1/reservationpayment'
,
updateReservationPayment: '/v1/reservationpayment/:sys_reservationPaymentId'
,
deleteReservationPayment: '/v1/reservationpayment/:sys_reservationPaymentId'
,
listReservationPayments2: '/v1/reservationpayments2'
,
getReservationPaymentByOrderId: '/v1/reservationpaymentbyorderid/:orderId'
,
getReservationPaymentByPaymentId: '/v1/reservationpaymentbypaymentid/:paymentId'
,
getReservationPayment2: '/v1/reservationpayment2/:sys_reservationPaymentId'
},
sys_paymentCustomer: {
getPaymentCustomerByUserId: '/v1/paymentcustomers/:userId'
,
listPaymentCustomers: '/v1/paymentcustomers'
},
sys_paymentMethod: {
listPaymentCustomerMethods: '/v1/paymentcustomermethods/:userId'
}
};
ReviewSystem Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const reviewSystemAxiosInstance = axios.create({
baseURL: CONFIG.reviewSystemServiceUrl
});
reviewSystemAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default reviewSystemAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await reviewSystemAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const reviewSystemEndpoints = {
reviewAggregate: {
listReviewAggregates: '/v1/reviewaggregates'
,
getReviewAggregate: '/v1/reviewaggregates/:reviewAggregateId'
},
review: {
getReview: '/v1/reviews/:reviewId'
,
createReview: '/v1/reviews'
,
deleteReview: '/v1/reviews/:reviewId'
,
listReviews: '/v1/reviews'
,
updateReview: '/v1/reviews/:reviewId'
}
};
Auth Axios Configuration
import axios from 'axios';
import { CONFIG } from 'src/global-config';
const authAxiosInstance = axios.create({
baseURL: CONFIG.authServiceUrl
});
authAxiosInstance.interceptors.response.use(
(response) => response,
(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong!')
);
export default authAxiosInstance;
Fetcher Utility
export const fetcher = async (args) => {
try {
const [url, config] = Array.isArray(args) ? args : [args];
const res = await authAxiosInstance.get(url, { ...config });
return res.data;
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
};
Service Endpoints
export const authEndpoints = {
login: "/login",
me: "/v1/users/:userId",
logout: "/logout",
user: {
getUser: '/v1/users/:userId'
,
updateUser: '/v1/users/:userId'
,
updateProfile: '/v1/profile/:userId'
,
createUser: '/v1/users'
,
deleteUser: '/v1/users/:userId'
,
archiveProfile: '/v1/archiveprofile/:userId'
,
listUsers: '/v1/users'
,
searchUsers: '/v1/searchusers'
,
updateUserRole: '/v1/userrole/:userId'
,
updateUserPassword: '/v1/userpassword/:userId'
,
updateUserPasswordByAdmin: '/v1/userpasswordbyadmin/:userId'
,
getBriefUser: '/v1/briefuser/:userId'
,
registerUser: '/v1/registeruser'
},
userGroup: {
createUserGroup: '/v1/usergroups'
,
updateUserGroup: '/v1/usergroups/:userGroupId'
,
deleteUserGroup: '/v1/usergroups/:userGroupId'
,
getUserGroup: '/v1/usergroups/:userGroupId'
,
listUserGroups: '/v1/usergroups'
},
userGroupMember: {
getUserGroupMember: '/v1/usergroupmembers/:userGroupMemberId'
,
createUserGroupMember: '/v1/usergroupmembers'
,
deleteUserGroupMember: '/v1/usergroupmembers/:userGroupMemberId'
,
listUserGroupMembers: '/v1/listusergroupmembers/:groupId'
}
};
Service Integration
Messaging Service Integration
The Messaging service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
MessageThreaddata object management -
MessageReportdata object management -
Messagedata object management
PropertyCatalog Service Integration
The PropertyCatalog service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
ListingCalendardata object management -
ListingAmenitydata object management -
Listingdata object management -
ListingLocaleTextdata object management
AdminPanel Service Integration
The AdminPanel service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
LocalizationSettingdata object management -
AdminDisputeActiondata object management -
ApiKeydata object management -
FinancialReportdata object management -
AuditLogdata object management -
GdprActiondata object management
BookingManagement Service Integration
The BookingManagement service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
Reservationdata object management -
PaymentRecorddata object management -
Disputedata object management -
Sys_reservationPaymentdata object management -
Sys_paymentCustomerdata object management -
Sys_paymentMethoddata object management
ReviewSystem Service Integration
The ReviewSystem service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
ReviewAggregatedata object management -
Reviewdata object management
Auth Service Integration
The Auth service is integrated using:
- Service-specific Axios instance with base URL configuration
- Dynamic endpoint generation based on business logic
- Error handling through response interceptors
- Fetcher utility for data retrieval
Available Endpoints:
-
Userdata object management -
UserGroupdata object management -
UserGroupMemberdata object management
Request/Response Patterns
Standard Request Format
Request Structure
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await messagingAxiosInstance.post('/endpoint', data);
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await propertyCatalogAxiosInstance.post('/endpoint', data);
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await adminPanelAxiosInstance.post('/endpoint', data);
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await bookingManagementAxiosInstance.post('/endpoint', data);
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await reviewSystemAxiosInstance.post('/endpoint', data);
// Simple GET request
const response = await fetcher('/endpoint');
// GET request with parameters
const response = await fetcher(['/endpoint', { params: { id: 1 } }]);
// POST request
const response = await authAxiosInstance.post('/endpoint', data);
Response Handling
Standard Response Format
// Success response
const response = await fetcher('/endpoint');
// response contains the data directly
// Error handling
try {
const response = await fetcher('/endpoint');
} catch (error) {
console.error('API Error:', error);
// Error is already processed by the interceptor
}
Pagination Handling
Pagination Implementation
// Pagination is handled by the data grid component
// The MUI DataGrid handles pagination automatically
Error Handling Patterns
Error Classification
Error Types
// Basic error handling through Axios interceptors
// Errors are processed and simplified before reaching components
Error Handler
Centralized Error Handling
class APIErrorHandler {
handleError(error) {
if (error.response) {
// Server responded with error status
return this.handleServerError(error);
} else if (error.request) {
// Network error
return this.handleNetworkError(error);
} else {
// Other error
return this.handleUnknownError(error);
}
}
handleServerError(error) {
const { status, data } = error.response;
switch (status) {
case 400:
return new ValidationError(
data.message || 'Validation failed',
data.errors || []
);
case 401:
return new AuthenticationError(
data.message || 'Authentication required'
);
case 403:
return new AuthorizationError(
data.message || 'Access denied'
);
case 404:
return new APIError(
data.message || 'Resource not found',
404,
'NOT_FOUND'
);
case 429:
return new APIError(
data.message || 'Rate limit exceeded',
429,
'RATE_LIMIT'
);
case 500:
return new APIError(
data.message || 'Internal server error',
500,
'SERVER_ERROR'
);
default:
return new APIError(
data.message || 'Unknown server error',
status,
'UNKNOWN_ERROR'
);
}
}
handleNetworkError(error) {
return new NetworkError(
'Network error occurred',
error
);
}
handleUnknownError(error) {
return new APIError(
error.message || 'Unknown error occurred',
0,
'UNKNOWN_ERROR'
);
}
}
Retry Mechanisms
Exponential Backoff Retry
class RetryManager {
constructor(options = {}) {
this.maxRetries = options.maxRetries || 3;
this.baseDelay = options.baseDelay || 1000;
this.maxDelay = options.maxDelay || 10000;
this.retryableStatusCodes = options.retryableStatusCodes || [408, 429, 500, 502, 503, 504];
}
async executeWithRetry(operation, context = {}) {
let lastError;
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (attempt === this.maxRetries || !this.shouldRetry(error)) {
break;
}
const delay = this.calculateDelay(attempt);
await this.sleep(delay);
}
}
throw lastError;
}
shouldRetry(error) {
return false;
}
calculateDelay(attempt) {
return 0;
}
sleep(ms) {
return Promise.resolve();
}
}
Performance Optimization
Request Batching
Batch Request Manager
class BatchRequestManager {
constructor(apiClient) {
this.apiClient = apiClient;
this.pendingRequests = new Map();
this.batchTimeout = 100; // 100ms
}
async batchRequest(endpoint, data, options = {}) {
const batchKey = this.generateBatchKey(endpoint, options);
if (!this.pendingRequests.has(batchKey)) {
this.pendingRequests.set(batchKey, []);
}
const request = {
data: data,
resolve: null,
reject: null,
timestamp: Date.now()
};
const promise = new Promise((resolve, reject) => {
request.resolve = resolve;
request.reject = reject;
});
this.pendingRequests.get(batchKey).push(request);
// Process batch after timeout
setTimeout(() => this.processBatch(batchKey), this.batchTimeout);
return promise;
}
async processBatch(batchKey) {
const requests = this.pendingRequests.get(batchKey);
if (!requests || requests.length === 0) return;
this.pendingRequests.delete(batchKey);
try {
const [serviceName, endpoint] = batchKey.split(':');
const batchData = requests.map(req => req.data);
const response = await this.apiClient.post(`/${endpoint}/batch`, {
requests: batchData
});
requests.forEach((request, index) => {
if (response.data.results[index].success) {
request.resolve(response.data.results[index].data);
} else {
request.reject(new Error(response.data.results[index].error));
}
});
} catch (error) {
requests.forEach(request => {
request.reject(error);
});
}
}
}