Integration Examples
Real-world integration examples for common use cases with the Flotac API.
Customer Portal Integration
Build a customer-facing portal where customers can view their vehicles and service history.
Customer Dashboard
const BASE_URL = 'https://chwjbbvcqsxxgaytqlix.supabase.co/functions/v1/api-gateway';
class CustomerPortal {
constructor(apiKey) {
this.apiKey = apiKey;
this.headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
}
async getCustomerDashboard(customerId) {
// Fetch customer details, vehicles, and recent service orders in parallel
const [customer, vehicles, serviceOrders, invoices] = await Promise.all([
this.fetch(`/api/v1/customers/${customerId}`),
this.fetch(`/api/v1/vehicles?customer_id=${customerId}`),
this.fetch(`/api/v1/service-orders?customer_id=${customerId}&sort_by=created_at&sort_order=desc&page_size=10`),
this.fetch(`/api/v1/invoices?customer_id=${customerId}&status=sent&sort_by=due_date`)
]);
return {
customer: customer.data,
vehicles: vehicles.data,
recentServiceOrders: serviceOrders.data,
pendingInvoices: invoices.data.filter(inv => inv.payment_status !== 'paid')
};
}
async fetch(endpoint) {
const response = await fetch(`${BASE_URL}${endpoint}`, { headers: this.headers });
return response.json();
}
}
// Usage
const portal = new CustomerPortal(process.env.FLOTAC_API_KEY);
const dashboard = await portal.getCustomerDashboard('customer-uuid');
Fleet Management System
Track all vehicles in a fleet with maintenance schedules and alerts.
Fleet Monitor
class FleetManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://chwjbbvcqsxxgaytqlix.supabase.co/functions/v1/api-gateway';
}
async getFleetOverview() {
const vehicles = await this.fetchAll('/api/v1/vehicles?status=active');
const fleetStats = {
totalVehicles: vehicles.length,
byStatus: this.groupBy(vehicles, 'status'),
byMake: this.groupBy(vehicles, 'make'),
maintenanceDue: []
};
// Check for vehicles needing maintenance
for (const vehicle of vehicles) {
const serviceOrders = await this.fetch(
`/api/v1/service-orders?vehicle_id=${vehicle.id}&status=completed&sort_by=completed_at&sort_order=desc&page_size=1`
);
if (serviceOrders.data.length > 0) {
const lastService = new Date(serviceOrders.data[0].completed_at);
const daysSinceService = Math.floor((Date.now() - lastService) / (1000 * 60 * 60 * 24));
if (daysSinceService > 90) {
fleetStats.maintenanceDue.push({
vehicle,
daysSinceService,
lastServiceDate: lastService
});
}
}
}
return fleetStats;
}
async schedulePreventiveMaintenance(vehicleId, description, scheduledDate) {
const vehicle = await this.fetch(`/api/v1/vehicles/${vehicleId}`);
return this.post('/api/v1/service-orders', {
customer_id: vehicle.data.customer_id,
vehicle_id: vehicleId,
status: 'pending',
priority: 'normal',
description: description,
scheduled_start: scheduledDate,
estimated_hours: 2
});
}
groupBy(array, key) {
return array.reduce((acc, item) => {
const value = item[key] || 'unknown';
acc[value] = (acc[value] || 0) + 1;
return acc;
}, {});
}
async fetch(endpoint) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
return response.json();
}
async post(endpoint, data) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
async fetchAll(endpoint) {
let allData = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await this.fetch(`${endpoint}&page=${page}&page_size=100`);
allData.push(...response.data);
hasMore = response.meta.pagination.hasNextPage;
page++;
}
return allData;
}
}
Inventory Management
Monitor parts inventory and automate reorder alerts.
Low Stock Monitor
class InventoryMonitor {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://chwjbbvcqsxxgaytqlix.supabase.co/functions/v1/api-gateway';
}
async checkLowStockParts() {
const response = await fetch(
`${this.baseUrl}/api/v1/parts?low_stock=true&track_inventory=true`,
{
headers: { 'Authorization': `Bearer ${this.apiKey}` }
}
);
const result = await response.json();
if (!result.success) {
throw new Error(result.error.message);
}
return result.data.map(part => ({
partNumber: part.part_number,
name: part.name,
currentStock: part.quantity_on_hand,
reorderPoint: part.reorder_point,
suggestedOrderQty: Math.max(part.reorder_point * 2 - part.quantity_on_hand, 0),
lastCost: part.cost,
estimatedReorderCost: Math.max(part.reorder_point * 2 - part.quantity_on_hand, 0) * part.cost
}));
}
async generateReorderReport() {
const lowStockParts = await this.checkLowStockParts();
const report = {
generatedAt: new Date().toISOString(),
totalPartsLowStock: lowStockParts.length,
totalEstimatedCost: lowStockParts.reduce((sum, p) => sum + p.estimatedReorderCost, 0),
parts: lowStockParts.sort((a, b) =>
(a.currentStock / a.reorderPoint) - (b.currentStock / b.reorderPoint)
)
};
return report;
}
}
// Usage
const monitor = new InventoryMonitor(process.env.FLOTAC_API_KEY);
const report = await monitor.generateReorderReport();
console.log(`Low Stock Alert: ${report.totalPartsLowStock} parts need reordering`);
console.log(`Estimated Reorder Cost: $${report.totalEstimatedCost.toFixed(2)}`);
report.parts.forEach(part => {
console.log(`- ${part.partNumber}: ${part.currentStock}/${part.reorderPoint} (Order: ${part.suggestedOrderQty})`);
});
Automated Invoicing
Automatically generate and send invoices when service orders are completed.
Invoice Automation
class InvoiceAutomation {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://chwjbbvcqsxxgaytqlix.supabase.co/functions/v1/api-gateway';
}
async processCompletedServiceOrders() {
// Find completed service orders without invoices
const serviceOrders = await this.fetch(
'/api/v1/service-orders?status=completed&sort_by=completed_at&sort_order=desc'
);
const results = [];
for (const order of serviceOrders.data) {
// Check if invoice already exists
const existingInvoices = await this.fetch(
`/api/v1/invoices?service_order_id=${order.id}`
);
if (existingInvoices.data.length === 0) {
// Create invoice for this service order
const invoice = await this.createInvoiceForOrder(order);
results.push({
serviceOrderId: order.id,
orderNumber: order.order_number,
invoiceId: invoice.data.id,
invoiceNumber: invoice.data.invoice_number,
status: 'created'
});
}
}
return results;
}
async createInvoiceForOrder(serviceOrder) {
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + 30);
const invoice = {
customer_id: serviceOrder.customer_id,
service_order_id: serviceOrder.id,
status: 'draft',
invoice_date: new Date().toISOString().split('T')[0],
due_date: dueDate.toISOString().split('T')[0],
subtotal: serviceOrder.actual_cost || serviceOrder.estimated_cost || 0,
tax_rate: 0.08,
tax_amount: (serviceOrder.actual_cost || serviceOrder.estimated_cost || 0) * 0.08,
total_amount: (serviceOrder.actual_cost || serviceOrder.estimated_cost || 0) * 1.08,
notes: `Invoice for Service Order: ${serviceOrder.order_number}`
};
return this.post('/api/v1/invoices', invoice);
}
async sendInvoice(invoiceId) {
return this.put(`/api/v1/invoices/${invoiceId}`, {
status: 'sent',
sent_at: new Date().toISOString()
});
}
async fetch(endpoint) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
return response.json();
}
async post(endpoint, data) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
async put(endpoint, data) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
}
Python SDK Example
Complete Python client for the Flotac API.
import os
import requests
from typing import Optional, Dict, Any, List
from datetime import datetime, timedelta
class FlotacClient:
def __init__(self, api_key: str = None):
self.api_key = api_key or os.environ.get('FLOTAC_API_KEY')
self.base_url = 'https://chwjbbvcqsxxgaytqlix.supabase.co/functions/v1/api-gateway'
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
})
def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
url = f'{self.base_url}{endpoint}'
response = self.session.request(method, url, **kwargs)
result = response.json()
if not result.get('success'):
raise FlotacAPIError(
result.get('error', {}).get('code', 'UNKNOWN'),
result.get('error', {}).get('message', 'Unknown error')
)
return result
# Customers
def list_customers(self, **params) -> List[Dict]:
return self._request('GET', '/api/v1/customers', params=params)['data']
def get_customer(self, customer_id: str) -> Dict:
return self._request('GET', f'/api/v1/customers/{customer_id}')['data']
def create_customer(self, data: Dict) -> Dict:
return self._request('POST', '/api/v1/customers', json=data)['data']
def update_customer(self, customer_id: str, data: Dict) -> Dict:
return self._request('PUT', f'/api/v1/customers/{customer_id}', json=data)['data']
# Vehicles
def list_vehicles(self, customer_id: str = None, **params) -> List[Dict]:
if customer_id:
params['customer_id'] = customer_id
return self._request('GET', '/api/v1/vehicles', params=params)['data']
def create_vehicle(self, data: Dict) -> Dict:
return self._request('POST', '/api/v1/vehicles', json=data)['data']
# Service Orders
def list_service_orders(self, **params) -> List[Dict]:
return self._request('GET', '/api/v1/service-orders', params=params)['data']
def create_service_order(self, data: Dict) -> Dict:
return self._request('POST', '/api/v1/service-orders', json=data)['data']
def update_service_order(self, order_id: str, data: Dict) -> Dict:
return self._request('PUT', f'/api/v1/service-orders/{order_id}', json=data)['data']
# Invoices
def list_invoices(self, **params) -> List[Dict]:
return self._request('GET', '/api/v1/invoices', params=params)['data']
def create_invoice(self, data: Dict) -> Dict:
return self._request('POST', '/api/v1/invoices', json=data)['data']
# Parts
def list_parts(self, **params) -> List[Dict]:
return self._request('GET', '/api/v1/parts', params=params)['data']
def get_low_stock_parts(self) -> List[Dict]:
return self.list_parts(low_stock=True, track_inventory=True)
class FlotacAPIError(Exception):
def __init__(self, code: str, message: str):
self.code = code
self.message = message
super().__init__(f'{code}: {message}')
# Usage
if __name__ == '__main__':
client = FlotacClient()
# List active customers
customers = client.list_customers(status='active')
print(f'Found {len(customers)} active customers')
# Create a new customer
new_customer = client.create_customer({
'name': 'New Fleet Co',
'customer_type': 'fleet',
'email': 'info@newfleet.com',
'status': 'active'
})
print(f'Created customer: {new_customer["id"]}')
# Check low stock parts
low_stock = client.get_low_stock_parts()
print(f'Low stock alert: {len(low_stock)} parts need reordering')
Webhook Integration
Set up webhooks to receive real-time updates.
Webhook Handler (Express.js)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.FLOTAC_WEBHOOK_SECRET;
// Verify webhook signature
function verifySignature(payload, signature) {
const hash = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(JSON.stringify(payload))
.digest('hex');
return `sha256=${hash}` === signature;
}
// Webhook endpoint
app.post('/webhooks/flotac', (req, res) => {
const signature = req.headers['x-flotac-signature'];
if (!verifySignature(req.body, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const { event, data, timestamp } = req.body;
switch (event) {
case 'service_order.completed':
handleServiceOrderCompleted(data);
break;
case 'invoice.paid':
handleInvoicePaid(data);
break;
case 'vehicle.created':
handleVehicleCreated(data);
break;
case 'part.low_stock':
handleLowStock(data);
break;
default:
console.log(`Unhandled event: ${event}`);
}
res.json({ received: true });
});
function handleServiceOrderCompleted(data) {
console.log(`Service order completed: ${data.order_number}`);
// Trigger invoice generation
// Send customer notification
}
function handleInvoicePaid(data) {
console.log(`Invoice paid: ${data.invoice_number}`);
// Update accounting system
// Send receipt to customer
}
function handleVehicleCreated(data) {
console.log(`New vehicle registered: ${data.vin}`);
// Schedule initial inspection
}
function handleLowStock(data) {
console.log(`Low stock alert: ${data.part_number}`);
// Send notification to purchasing team
// Create purchase order
}
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Next Steps
- Quick Start - Get started in 5 minutes
- Authentication - Learn about authentication methods
- API Reference - Complete endpoint documentation