Code Examples
This page provides comprehensive code examples for integrating with the Centro Access API in various programming languages.
Authentication Setup
All API requests require authentication using an API key. Here's how to set it up:
JavaScript/Node.js
const API_KEY = 'your-api-key-here';
const BASE_URL = 'https://app.centroaccess.com/api/v1';
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
Python
import requests
API_KEY = 'your-api-key-here'
BASE_URL = 'https://app.centroaccess.com/api/v1'
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
cURL
API_KEY="your-api-key-here"
BASE_URL="https://app.centroaccess.com/api/v1"
# Use in requests like:
curl -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
"$BASE_URL/work-orders/"
Complete Workflow Examples
1. Create and Track Work Order
JavaScript/Node.js Implementation
const axios = require('axios');
class CentroAccessClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = 'https://app.centroaccess.com/api/v1';
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}
async createWorkOrder(workOrderData) {
try {
const response = await axios.post(
`${this.baseURL}/work-orders/`,
workOrderData,
{ headers: this.headers }
);
return response.data;
} catch (error) {
console.error('Error creating work order:', error.response?.data || error.message);
throw error;
}
}
async getWorkOrder(workOrderId) {
try {
const response = await axios.get(
`${this.baseURL}/work-orders/${workOrderId}/`,
{ headers: this.headers }
);
return response.data;
} catch (error) {
console.error('Error fetching work order:', error.response?.data || error.message);
throw error;
}
}
async listWorkOrders(filters = {}) {
try {
const params = new URLSearchParams(filters);
const response = await axios.get(
`${this.baseURL}/work-orders/?${params}`,
{ headers: this.headers }
);
return response.data;
} catch (error) {
console.error('Error listing work orders:', error.response?.data || error.message);
throw error;
}
}
}
// Usage example
async function main() {
const client = new CentroAccessClient('your-api-key-here');
// Create a work order
const newWorkOrder = await client.createWorkOrder({
client_name: "John Smith",
client_contact: "+256700123456",
service_category: "installation",
priority: "high",
additional_information: "Customer needs installation of new fiber connection",
latitude: 0.3476,
longitude: 32.5825,
preferred_time: "2024-12-01T10:00:00Z",
due_date: "2024-12-05"
});
console.log('Created work order:', newWorkOrder);
// Get the work order details
const workOrder = await client.getWorkOrder(newWorkOrder.work_order.id);
console.log('Work order details:', workOrder);
// List all work orders
const workOrders = await client.listWorkOrders({
status: 'dispatch',
priority: 'high'
});
console.log('High priority dispatch work orders:', workOrders);
}
main().catch(console.error);
Python Implementation
import requests
import json
from datetime import datetime, timedelta
class CentroAccessClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://app.centroaccess.com/api/v1'
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
def create_work_order(self, work_order_data):
"""Create a new work order"""
try:
response = requests.post(
f'{self.base_url}/work-orders/',
headers=self.headers,
json=work_order_data
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f'Error creating work order: {e}')
if hasattr(e.response, 'text'):
print(f'Response: {e.response.text}')
raise
def get_work_order(self, work_order_id):
"""Get work order details by ID"""
try:
response = requests.get(
f'{self.base_url}/work-orders/{work_order_id}/',
headers=self.headers
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f'Error fetching work order: {e}')
raise
def list_work_orders(self, **filters):
"""List work orders with optional filters"""
try:
response = requests.get(
f'{self.base_url}/work-orders/',
headers=self.headers,
params=filters
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f'Error listing work orders: {e}')
raise
# Usage example
def main():
client = CentroAccessClient('your-api-key-here')
# Create a work order
work_order_data = {
'client_name': 'Jane Doe',
'client_contact': '+256700987654',
'service_category': 'maintenance',
'priority': 'medium',
'additional_information': 'Regular maintenance check for fiber connection',
'latitude': 0.3476,
'longitude': 32.5825,
'preferred_time': (datetime.now() + timedelta(days=1)).isoformat(),
'due_date': (datetime.now() + timedelta(days=3)).strftime('%Y-%m-%d')
}
result = client.create_work_order(work_order_data)
print('Created work order:', json.dumps(result, indent=2))
# Get the work order details
work_order_id = result['work_order']['id']
work_order = client.get_work_order(work_order_id)
print('Work order details:', json.dumps(work_order, indent=2))
# List work orders with filters
work_orders = client.list_work_orders(
status='dispatch',
priority='medium'
)
print('Medium priority dispatch work orders:', json.dumps(work_orders, indent=2))
if __name__ == '__main__':
main()
2. Bulk Work Order Creation
JavaScript/Node.js Bulk Processing
async function createBulkWorkOrders(client, workOrdersData) {
const results = [];
for (const workOrderData of workOrdersData) {
try {
const result = await client.createWorkOrder(workOrderData);
results.push({
success: true,
data: result,
originalData: workOrderData
});
// Add delay to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
results.push({
success: false,
error: error.message,
originalData: workOrderData
});
}
}
return results;
}
// Usage
const bulkData = [
{
client_name: "Customer 1",
client_contact: "+256700111111",
service_category: "installation"
},
{
client_name: "Customer 2",
client_contact: "+256700222222",
service_category: "maintenance"
}
];
const results = await createBulkWorkOrders(client, bulkData);
console.log('Bulk creation results:', results);
Python Bulk Processing
import time
def create_bulk_work_orders(client, work_orders_data):
"""Create multiple work orders in bulk"""
results = []
for work_order_data in work_orders_data:
try:
result = client.create_work_order(work_order_data)
results.append({
'success': True,
'data': result,
'original_data': work_order_data
})
# Add delay to avoid rate limiting
time.sleep(0.1)
except Exception as e:
results.append({
'success': False,
'error': str(e),
'original_data': work_order_data
})
return results
# Usage
bulk_data = [
{
'client_name': 'Customer 1',
'client_contact': '+256700111111',
'service_category': 'installation'
},
{
'client_name': 'Customer 2',
'client_contact': '+256700222222',
'service_category': 'maintenance'
}
]
results = create_bulk_work_orders(client, bulk_data)
print('Bulk creation results:', json.dumps(results, indent=2))
3. Work Order Monitoring Dashboard
JavaScript/Node.js Dashboard
class WorkOrderDashboard {
constructor(client) {
this.client = client;
}
async getDashboardData() {
try {
// Get work orders by status
const [dispatch, inProgress, completed] = await Promise.all([
this.client.listWorkOrders({ status: 'dispatch' }),
this.client.listWorkOrders({ status: 'in-progress' }),
this.client.listWorkOrders({ status: 'completed' })
]);
// Get work orders by priority
const [high, medium, low] = await Promise.all([
this.client.listWorkOrders({ priority: 'high' }),
this.client.listWorkOrders({ priority: 'medium' }),
this.client.listWorkOrders({ priority: 'low' })
]);
return {
byStatus: {
dispatch: dispatch.results.length,
inProgress: inProgress.results.length,
completed: completed.results.length,
total: dispatch.results.length + inProgress.results.length + completed.results.length
},
byPriority: {
high: high.results.length,
medium: medium.results.length,
low: low.results.length
},
recentWorkOrders: dispatch.results.slice(0, 10) // Latest 10 dispatch orders
};
} catch (error) {
console.error('Error fetching dashboard data:', error);
throw error;
}
}
async printDashboard() {
const data = await this.getDashboardData();
console.log('=== Centro Access Dashboard ===');
console.log(`Total Work Orders: ${data.byStatus.total}`);
console.log(` Dispatch: ${data.byStatus.dispatch}`);
console.log(` In Progress: ${data.byStatus.inProgress}`);
console.log(` Completed: ${data.byStatus.completed}`);
console.log('');
console.log('Priority Breakdown:');
console.log(` High: ${data.byPriority.high}`);
console.log(` Medium: ${data.byPriority.medium}`);
console.log(` Low: ${data.byPriority.low}`);
console.log('');
console.log('Recent Work Orders:');
data.recentWorkOrders.forEach(wo => {
console.log(` ${wo.title} - ${wo.priority} priority`);
});
}
}
// Usage
const dashboard = new WorkOrderDashboard(client);
await dashboard.printDashboard();
Error Handling Examples
Comprehensive Error Handling
JavaScript/Node.js Error Handling
async function robustAPICall(client, operation, ...args) {
const maxRetries = 3;
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await client[operation](...args);
} catch (error) {
lastError = error;
if (error.response) {
// Server responded with error status
const status = error.response.status;
const message = error.response.data?.message || error.message;
console.log(`Attempt ${attempt} failed with status ${status}: ${message}`);
// Don't retry on client errors (4xx)
if (status >= 400 && status < 500) {
throw error;
}
// Retry on server errors (5xx) with exponential backoff
if (attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
} else {
// Network error or other issue
console.log(`Network error on attempt ${attempt}: ${error.message}`);
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
}
}
throw lastError;
}
// Usage
try {
const result = await robustAPICall(client, 'createWorkOrder', {
client_name: "Test Client",
client_contact: "+256700123456"
});
console.log('Success:', result);
} catch (error) {
console.error('Final error after retries:', error.message);
}
Python Error Handling
import time
import random
def robust_api_call(client, method_name, *args, **kwargs):
"""Make API call with retry logic and error handling"""
max_retries = 3
last_error = None
for attempt in range(1, max_retries + 1):
try:
method = getattr(client, method_name)
return method(*args, **kwargs)
except requests.exceptions.RequestException as e:
last_error = e
if hasattr(e, 'response') and e.response is not None:
status = e.response.status_code
message = e.response.json().get('message', str(e)) if e.response.headers.get('content-type', '').startswith('application/json') else str(e)
print(f'Attempt {attempt} failed with status {status}: {message}')
# Don't retry on client errors (4xx)
if 400 <= status < 500:
raise e
# Retry on server errors (5xx) with exponential backoff
if attempt < max_retries:
delay = (2 ** attempt) + random.uniform(0, 1) # 2s, 4s, 8s + jitter
print(f'Retrying in {delay:.1f}s...')
time.sleep(delay)
else:
# Network error
print(f'Network error on attempt {attempt}: {e}')
if attempt < max_retries:
time.sleep(2)
raise last_error
# Usage
try:
result = robust_api_call(client, 'create_work_order', {
'client_name': 'Test Client',
'client_contact': '+256700123456'
})
print('Success:', json.dumps(result, indent=2))
except Exception as e:
print(f'Final error after retries: {e}')
Integration Patterns
Webhook Simulation (Polling)
Since Centro Access doesn't provide webhooks yet, you can implement polling to monitor work order changes:
JavaScript/Node.js Polling Monitor
class WorkOrderMonitor {
constructor(client, pollInterval = 30000) { // 30 seconds
this.client = client;
this.pollInterval = pollInterval;
this.knownWorkOrders = new Map();
this.isRunning = false;
}
async start() {
this.isRunning = true;
console.log('Starting work order monitor...');
while (this.isRunning) {
try {
await this.checkForUpdates();
} catch (error) {
console.error('Error checking for updates:', error.message);
}
await this.sleep(this.pollInterval);
}
}
stop() {
this.isRunning = false;
console.log('Work order monitor stopped');
}
async checkForUpdates() {
const workOrders = await this.client.listWorkOrders();
for (const workOrder of workOrders.results) {
const id = workOrder.id;
const currentVersion = {
status: workOrder.status,
priority: workOrder.priority,
updatedAt: workOrder.updated_at
};
if (this.knownWorkOrders.has(id)) {
const previousVersion = this.knownWorkOrders.get(id);
if (previousVersion.status !== currentVersion.status) {
this.onStatusChange(workOrder, previousVersion.status, currentVersion.status);
}
if (previousVersion.updatedAt !== currentVersion.updatedAt) {
this.onWorkOrderUpdated(workOrder);
}
} else {
this.onNewWorkOrder(workOrder);
}
this.knownWorkOrders.set(id, currentVersion);
}
}
onNewWorkOrder(workOrder) {
console.log(`New work order created: ${workOrder.title}`);
}
onStatusChange(workOrder, oldStatus, newStatus) {
console.log(`Work order ${workOrder.title} status changed: ${oldStatus} → ${newStatus}`);
}
onWorkOrderUpdated(workOrder) {
console.log(`Work order updated: ${workOrder.title}`);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Usage
const monitor = new WorkOrderMonitor(client, 30000); // Check every 30 seconds
monitor.start();
// Stop after some time or on process exit
process.on('SIGINT', () => {
monitor.stop();
process.exit(0);
});
Best Practices
1. Rate Limiting
class RateLimitedClient {
constructor(apiKey, requestsPerSecond = 5) {
this.client = new CentroAccessClient(apiKey);
this.requestsPerSecond = requestsPerSecond;
this.requestQueue = [];
this.isProcessing = false;
}
async request(method, ...args) {
return new Promise((resolve, reject) => {
this.requestQueue.push({ method, args, resolve, reject });
this.processQueue();
});
}
async processQueue() {
if (this.isProcessing || this.requestQueue.length === 0) return;
this.isProcessing = true;
const interval = 1000 / this.requestsPerSecond;
while (this.requestQueue.length > 0) {
const { method, args, resolve, reject } = this.requestQueue.shift();
try {
const result = await this.client[method](...args);
resolve(result);
} catch (error) {
reject(error);
}
if (this.requestQueue.length > 0) {
await new Promise(resolve => setTimeout(resolve, interval));
}
}
this.isProcessing = false;
}
}
2. Data Validation
function validateWorkOrderData(data) {
const errors = [];
if (!data.client_name || data.client_name.trim().length === 0) {
errors.push('client_name is required');
}
if (!data.client_contact || !/^\+\d{10,15}$/.test(data.client_contact)) {
errors.push('client_contact must be a valid phone number with country code');
}
if (data.service_category && !['installation', 'maintenance', 'repair', 'survey'].includes(data.service_category)) {
errors.push('service_category must be one of: installation, maintenance, repair, survey');
}
if (data.priority && !['low', 'medium', 'high', 'urgent'].includes(data.priority)) {
errors.push('priority must be one of: low, medium, high, urgent');
}
if (data.latitude && (data.latitude < -90 || data.latitude > 90)) {
errors.push('latitude must be between -90 and 90');
}
if (data.longitude && (data.longitude < -180 || data.longitude > 180)) {
errors.push('longitude must be between -180 and 180');
}
return errors;
}
// Usage
const workOrderData = {
client_name: "John Doe",
client_contact: "+256700123456",
service_category: "installation"
};
const validationErrors = validateWorkOrderData(workOrderData);
if (validationErrors.length > 0) {
console.error('Validation errors:', validationErrors);
} else {
const result = await client.createWorkOrder(workOrderData);
}
Testing Your Integration
Unit Test Example (Jest)
const { CentroAccessClient } = require('./centro-access-client');
describe('Centro Access API Integration', () => {
let client;
beforeAll(() => {
client = new CentroAccessClient(process.env.CENTRO_ACCESS_TEST_API_KEY);
});
test('should create work order successfully', async () => {
const workOrderData = {
client_name: 'Test Client',
client_contact: '+256700123456',
service_category: 'installation',
priority: 'medium'
};
const result = await client.createWorkOrder(workOrderData);
expect(result.success).toBe(true);
expect(result.work_order).toBeDefined();
expect(result.work_order.title).toBe('Test Client - Installation');
expect(result.work_order.status).toBe('dispatch');
});
test('should handle validation errors', async () => {
const invalidData = {
client_name: '', // Empty name should fail
client_contact: 'invalid-phone'
};
await expect(client.createWorkOrder(invalidData))
.rejects
.toThrow();
});
});
Next Steps
After implementing these examples:
- Test thoroughly in a development environment
- Implement proper logging for production monitoring
- Set up error alerting for failed API calls
- Monitor API usage to stay within rate limits
- Keep your API key secure and rotate it regularly
For more specific integration questions, please contact our support team or refer to the main API documentation.