Integration Examples
Practical examples of how to integrate with the Sakneen API.
Creating a Lead
The most common operation is creating a new lead in the system.
Basic Lead Creation
const createLead = async (leadData) => {
try {
const baseDomain = process.env.SAKNEEN_DOMAIN; // your assigned domain
const response = await fetch(`https://${baseDomain}/external/apis/v1.0/leads`, {
method: 'POST',
headers: {
'api-key': process.env.SAKNEEN_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(leadData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
console.log('Lead created successfully:', result.newLead);
return result;
} catch (error) {
console.error('Error creating lead:', error);
throw error;
}
};
// Usage
const leadData = {
name: 'Jane Smith',
phoneNumber: '+1987654321',
project: 'Riverside Apartments',
email: '[email protected]'
};
createLead(leadData);
Lead Creation with Validation
const validateLead = (leadData) => {
const errors = [];
if (!leadData.name || leadData.name.trim().length === 0) {
errors.push('Name is required');
}
if (!leadData.phoneNumber || !/^\+\d{10,15}$/.test(leadData.phoneNumber)) {
errors.push('Valid phone number is required');
}
if (leadData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(leadData.email)) {
errors.push('Invalid email format');
}
return errors;
};
const createLeadSafely = async (leadData) => {
// Validate input
const validationErrors = validateLead(leadData);
if (validationErrors.length > 0) {
throw new Error(`Validation failed: ${validationErrors.join(', ')}`);
}
// Create lead
return await createLead(leadData);
};
Listing Units
Retrieve a paginated list of units with optional filtering and sorting.
Basic Unit Listing
const listUnits = async ({ page = 1, limit = 10, statuses, sortBy, order } = {}) => {
const baseDomain = process.env.SAKNEEN_DOMAIN;
const params = new URLSearchParams({ page, limit });
if (sortBy) params.append('sortBy', sortBy);
if (order) params.append('order', order);
if (statuses) {
for (const status of statuses) {
params.append('statuses', status);
}
}
const response = await fetch(
`https://${baseDomain}/external/apis/v1.0/units?${params}`,
{
method: 'GET',
headers: { 'api-key': process.env.SAKNEEN_API_KEY },
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};
// Usage - list available units, sorted by price ascending
const result = await listUnits({
page: 1,
limit: 20,
statuses: ['available'],
sortBy: 'price',
order: 'asc'
});
console.log(`Page 1 of ${result.pagination.pages} (${result.pagination.total} total units)`);
result.data.forEach(unit => {
console.log(`${unit.unitId}: ${unit.title} - ${unit.price} ${unit.priceCurrency}`);
});
Paginate Through All Units
const getAllUnits = async (statuses) => {
const allUnits = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const result = await listUnits({ page, limit: 100, statuses });
allUnits.push(...result.data);
hasMore = page < result.pagination.pages;
page++;
}
return allUnits;
};
// Fetch all available units
const availableUnits = await getAllUnits(['available']);
console.log(`Total available units: ${availableUnits.length}`);
Getting a Single Unit
Retrieve a single unit by its slug for detail pages.
const getUnitBySlug = async (slug) => {
const baseDomain = process.env.SAKNEEN_DOMAIN;
const response = await fetch(
`https://${baseDomain}/external/apis/v1.0/units/${encodeURIComponent(slug)}`,
{
method: 'GET',
headers: { 'api-key': process.env.SAKNEEN_API_KEY },
}
);
if (response.status === 404) {
return null; // Unit not found
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
return result.data;
};
// Usage
const unit = await getUnitBySlug('luxury-apartment-vh-12');
if (unit) {
console.log(`${unit.title} - ${unit.price} ${unit.priceCurrency}`);
console.log(`Bedrooms: ${unit.beds}, Bathrooms: ${unit.bathrooms}`);
console.log(`Status: ${unit.status}`);
console.log(`Property Type: ${unit.propertyType?.name}`);
} else {
console.log('Unit not found');
}
Error Handling
Comprehensive Error Handling
const handleApiResponse = async (response) => {
if (response.ok) {
return response.json();
}
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
try {
const errorData = await response.json();
if (errorData.message) {
errorMessage = Array.isArray(errorData.message)
? errorData.message.map(m => typeof m === 'object' ? JSON.stringify(m) : m).join(', ')
: errorData.message;
}
} catch (e) {
// If response is not JSON, use default error message
}
throw new Error(errorMessage);
};
const apiRequest = async (path, options = {}) => {
const baseDomain = process.env.SAKNEEN_DOMAIN;
try {
const response = await fetch(`https://${baseDomain}/external/apis/v1.0${path}`, {
...options,
headers: {
'api-key': process.env.SAKNEEN_API_KEY,
...options.headers,
},
});
return await handleApiResponse(response);
} catch (error) {
console.error(`API request failed [${path}]:`, error.message);
throw error;
}
};
// Usage
const units = await apiRequest('/units?page=1&limit=10');
const unit = await apiRequest('/units/luxury-apartment-vh-12');
const lead = await apiRequest('/leads', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John Doe', phoneNumber: '+1234567890' }),
});
Webhook Integration
If you need to receive notifications when leads are processed:
const express = require('express');
const app = express();
app.use(express.json());
// Webhook endpoint to receive lead status updates
app.post('/webhook/lead-status', (req, res) => {
const { leadId, status, timestamp } = req.body;
console.log(`Lead ${leadId} status updated to: ${status} at ${timestamp}`);
// Process the webhook data
// Update your local database, send notifications, etc.
res.status(200).send('OK');
});
app.listen(3001, () => {
console.log('Webhook server listening on port 3001');
});
Best Practices
- Always validate input data before sending to the API
- Implement proper error handling for all API calls
- Use environment variables for sensitive data like API keys
- Implement retry logic for transient failures
- Log API interactions for debugging and monitoring
- Rate limit your requests to avoid overwhelming the API
- Use pagination efficiently -- prefer smaller page sizes (10-50) over the maximum (100)
- Cache unit slugs when building detail page links to avoid redundant list requests