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

  1. Capture shipping requirements from your application
  2. Call Flash Americas API to get rates
  3. Present options to the user
  4. Process selection and create shipment
  5. 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