Custom Integration
Build a custom integration with the Flash Americas API for your specific platform or requirements. This guide covers common patterns and best practices.
Integration Architecture
Basic Flow
- Capture shipping requirements from your application
- Call Flash Americas API to get rates
- Present options to the user
- Process selection and create shipment
- Track and update status
API Integration Points
Core integration functionsjavascript
class CustomFlashAmericasIntegration {
constructor(apiKey, environment = 'production') {
this.apiKey = apiKey;
this.baseUrl = 'https://ship.flashamericas.com/api/v1';
}
async getShippingRates(shipment) {
const response = await this.apiCall('/quote', {
method: 'POST',
body: JSON.stringify({
originAddress: shipment.origin,
destinationAddress: shipment.destination,
cargo: shipment.items,
shipDate: shipment.shipDate
})
});
return response.data.rates;
}
async createShipment(quoteId, shipmentDetails) {
return await this.apiCall('/shipments', {
method: 'POST',
body: JSON.stringify({
quoteId,
...shipmentDetails
})
});
}
async trackShipment(shipmentId) {
return await this.apiCall(`/shipments/${shipmentId}/tracking`);
}
async apiCall(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
}E-commerce Platform Integration
Generic E-commerce Flow
E-commerce checkout integrationjavascript
class EcommerceShippingIntegration {
constructor(flashAmericasClient) {
this.client = flashAmericasClient;
}
async calculateShippingRates(cart, shippingAddress) {
try {
// Convert cart to Flash Americas format
const cargo = cart.items.map(item => ({
weight: item.weight,
length: item.dimensions?.length || 12,
width: item.dimensions?.width || 12,
height: item.dimensions?.height || 12,
quantity: item.quantity,
description: item.name,
value: item.price * item.quantity
}));
const rates = await this.client.getShippingRates({
origin: this.getWarehouseAddress(),
destination: shippingAddress,
items: cargo,
shipDate: this.getNextBusinessDay()
});
// Format for your platform
return rates.map(rate => ({
id: rate.id,
name: `${rate.provider} ${rate.service}`,
price: rate.cost,
estimatedDelivery: rate.deliveryDate,
transitDays: rate.transitDays
}));
} catch (error) {
console.error('Shipping calculation failed:', error);
return this.getFallbackRates();
}
}
async processOrder(order, selectedShippingRate) {
try {
// Create shipment when order is confirmed
const shipment = await this.client.createShipment(
selectedShippingRate.quoteId,
{
shipperInfo: this.getShipperInfo(),
consigneeInfo: this.formatConsigneeInfo(order.customer),
items: order.items
}
);
// Store shipment info in your database
await this.storeShipmentInfo(order.id, shipment);
return shipment;
} catch (error) {
console.error('Shipment creation failed:', error);
throw error;
}
}
}Database Schema
Store Flash Americas data in your system:
Database tablessql
-- Shipping rates cache
CREATE TABLE shipping_rates_cache (
id SERIAL PRIMARY KEY,
cache_key VARCHAR(255) UNIQUE,
rates_data JSONB,
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
-- Shipments tracking
CREATE TABLE shipments (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES orders(id),
flash_americas_shipment_id VARCHAR(255),
tracking_number VARCHAR(255),
carrier VARCHAR(100),
service VARCHAR(100),
status VARCHAR(50),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Shipping events/tracking
CREATE TABLE shipping_events (
id SERIAL PRIMARY KEY,
shipment_id INTEGER REFERENCES shipments(id),
event_type VARCHAR(100),
event_date TIMESTAMP,
location VARCHAR(255),
description TEXT,
created_at TIMESTAMP DEFAULT NOW()
);Caching Strategy
Implement caching to improve performance:
Rate caching implementationjavascript
class RateCachingService {
constructor(cacheProvider) {
this.cache = cacheProvider; // Redis, Memcached, etc.
this.cacheTTL = 300; // 5 minutes
}
generateCacheKey(origin, destination, items) {
const normalized = JSON.stringify({
origin: this.normalizeAddress(origin),
destination: this.normalizeAddress(destination),
items: items.map(item => ({
weight: item.weight,
dimensions: item.dimensions,
quantity: item.quantity
}))
});
return `rates:${this.hash(normalized)}`;
}
async getCachedRates(cacheKey) {
try {
const cached = await this.cache.get(cacheKey);
return cached ? JSON.parse(cached) : null;
} catch (error) {
console.error('Cache read error:', error);
return null;
}
}
async setCachedRates(cacheKey, rates) {
try {
await this.cache.setex(
cacheKey,
this.cacheTTL,
JSON.stringify(rates)
);
} catch (error) {
console.error('Cache write error:', error);
}
}
async getShippingRatesWithCache(origin, destination, items) {
const cacheKey = this.generateCacheKey(origin, destination, items);
// Try cache first
let rates = await this.getCachedRates(cacheKey);
if (!rates) {
// Fetch from API
rates = await this.flashAmericasClient.getShippingRates({
origin, destination, items
});
// Cache the results
await this.setCachedRates(cacheKey, rates);
}
return rates;
}
}Webhook Integration
Handle real-time updates:
Webhook handlerjavascript
app.post('/webhooks/flash-americas', async (req, res) => {
try {
// Verify webhook signature
const signature = req.headers['x-flash-americas-signature'];
if (!this.verifyWebhookSignature(req.body, signature)) {
return res.status(401).send('Unauthorized');
}
const event = req.body;
switch (event.eventType) {
case 'shipment.picked_up':
await this.updateShipmentStatus(
event.data.shipmentId,
'picked_up'
);
await this.notifyCustomer(event.data, 'Package picked up');
break;
case 'shipment.delivered':
await this.updateShipmentStatus(
event.data.shipmentId,
'delivered'
);
await this.notifyCustomer(event.data, 'Package delivered');
break;
case 'shipment.exception':
await this.handleDeliveryException(event.data);
break;
}
res.status(200).send('OK');
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).send('Error');
}
});Error Handling
Implement robust error handling:
Error handling strategyjavascript
class RobustShippingService {
async getShippingRatesWithFallback(shipmentData) {
try {
// Try Flash Americas first
return await this.flashAmericasClient.getShippingRates(shipmentData);
} catch (error) {
console.error('Flash Americas rate error:', error);
if (error.code === 'RATE_LIMIT_ERROR') {
// Implement exponential backoff
await this.sleep(error.retryAfter * 1000);
return this.getShippingRatesWithFallback(shipmentData);
}
if (error.code === 'INVALID_ADDRESS') {
// Try address correction
const correctedAddress = await this.correctAddress(
shipmentData.destination
);
if (correctedAddress) {
shipmentData.destination = correctedAddress;
return this.getShippingRatesWithFallback(shipmentData);
}
}
// Return fallback rates if available
return this.getFallbackRates(shipmentData);
}
}
getFallbackRates(shipmentData) {
// Calculate basic rates based on weight/distance
const baseRate = this.calculateBasicRate(shipmentData);
return [{
id: 'fallback-standard',
provider: 'Standard',
service: 'Ground',
cost: baseRate,
transitDays: 5,
deliveryDate: this.addBusinessDays(new Date(), 5)
}];
}
}Next Steps
- API Reference - Complete API documentation
- Examples - See working implementations
- Testing - Validate your integration
- Support - Get help with custom requirements
