Last updated

Customer Package Choice

This guide demonstrates how to integrate Hubby eSIM into your airline booking flow, allowing customers to choose their preferred data package and managing the communication flow through your existing channels.

Overview

In this integration pattern:

  1. Your system fetches available packages for the destination
  2. Customer selects their preferred package during booking
  3. Booking is created with the specific package ID
  4. You receive a promo code to include in your booking confirmation email
  5. Customer redeems the code in the Hubby app

Prerequisites

  • A Hubby Partner account with API access
  • Your API credentials (public key and secret)
  • Ability to modify your booking flow UI
  • Email template system for confirmation emails

API Endpoints

Hubby provides two API endpoints for different environments:

  • Production: https://api.hubbyesim.com/api - Use this for live applications
  • Staging: https://api-staging.hubby.dev/api - Use this for testing and development

Always test thoroughly in staging before using production.

Implementation Steps

1. Authentication Setup

First, implement the HMAC authentication system:

const crypto = require('crypto');

function generateHeaders(method, path, timestamp) {
  const payload = timestamp + method + path;
  const signature = crypto
    .createHmac('sha256', process.env.HUBBY_API_SECRET)
    .update(payload)
    .digest('hex');

  return {
    'x-api-key': process.env.HUBBY_API_KEY,
    'x-timestamp': timestamp,
    'x-signature': signature,
    'Content-Type': 'application/json'
  };
}

2. Fetching Available Packages

When a customer books a flight, fetch the available packages for their destination:

// Use staging for development, production for live
const API_BASE_URL = process.env.NODE_ENV === 'production' 
  ? 'https://api.hubbyesim.com'
  : 'https://api-staging.hubby.dev';

async function getPackagesForCountry(countryCode) {
  const timestamp = Date.now().toString();
  const path = `/api/countries/${countryCode}/packages`;
  
  const response = await fetch(`${API_BASE_URL}${path}`, {
    method: 'GET',
    headers: generateHeaders('GET', path, timestamp)
  });

  const data = await response.json();
  
  if (data.success) {
    // Format packages for display
    return data.data[countryCode].map(package => ({
      id: package.id,
      label: package.label,
      size: package.bytes,
      price: package.price,
      validity: package.days
    }));
  }
  
  throw new Error('Failed to fetch packages');
}

3. Package Selection UI

Example React component for package selection:

function PackageSelector({ countryCode, onSelect }) {
  const [packages, setPackages] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function loadPackages() {
      try {
        const packages = await getPackagesForCountry(countryCode);
        setPackages(packages);
      } catch (err) {
        setError('Failed to load packages');
      } finally {
        setLoading(false);
      }
    }
    loadPackages();
  }, [countryCode]);

  if (loading) return <div>Loading packages...</div>;
  if (error) return <div>{error}</div>;

  return (
    <div className="package-grid">
      {packages.map(pkg => (
        <div key={pkg.id} className="package-card">
          <h3>{pkg.label}</h3>
          <p>Valid for {pkg.validity} days</p>
          <p>Price: ${pkg.price}</p>
          <button onClick={() => onSelect(pkg)}>
            Select Package
          </button>
        </div>
      ))}
    </div>
  );
}

4. Creating the Booking

Once a package is selected, create the booking with the specific package ID:

async function createEsimBooking(bookingData) {
  const timestamp = Date.now().toString();
  const path = '/api/bookings';
  
  const response = await fetch(`${API_BASE_URL}/api/bookings`, {
    method: 'POST',
    headers: generateHeaders('POST', path, timestamp),
    body: JSON.stringify({
      booking_id: bookingData.bookingId,
      departure_date: bookingData.flightDate,
      email: bookingData.customerEmail,
      first_name: bookingData.firstName,
      last_name: bookingData.lastName,
      package_specifications: [{
        destination: bookingData.countryCode,
        package_id: bookingData.selectedPackageId // When set, this spec is resolved only by this ID; other fields in this entry are ignored
      }],
      communication_options: {
        should_send_message: false // We'll handle communication
      }
    })
  });

  return await response.json();
}

5. Handling the Response and Email Integration

async function handleBookingAndSendEmail(bookingResponse, emailTemplate) {
  if (bookingResponse.success) {
    const promoCode = bookingResponse.data.promo_codes[0].promo_code;
    
    // Store the Hubby booking reference
    await updateFlightBooking({
      hubbyBookingId: bookingResponse.data.id,
      promoCode: promoCode
    });

    // Add eSIM details to confirmation email
    const emailContent = emailTemplate.replace(
      '{{ESIM_DETAILS}}',
      `
      Your eSIM Promo Code: ${promoCode}
      
      To activate your eSIM:
      1. Download the Hubby app
      2. Enter your promo code
      3. Follow the installation instructions
      `
    );

    await sendConfirmationEmail(emailContent);
  } else {
    // Handle error cases
    console.error('Booking creation failed:', bookingResponse.error);
  }
}

Complete Integration Example

Here's how to put it all together in your booking flow:

const express = require('express');
const router = express.Router();

router.post('/flight-bookings', async (req, res) => {
  try {
    // 1. Create flight booking
    const flightBooking = await createFlightBooking(req.body);

    // 2. If eSIM was selected
    if (req.body.includeEsim) {
      // 3. Create Hubby eSIM booking
      const esimBooking = await createEsimBooking({
        bookingId: flightBooking.id,
        flightDate: flightBooking.departureDate,
        customerEmail: flightBooking.customerEmail,
        firstName: flightBooking.firstName,
        lastName: flightBooking.lastName,
        countryCode: flightBooking.destination,
        selectedPackageId: req.body.selectedPackageId
      });

      // 4. Handle response and send email
      await handleBookingAndSendEmail(
        esimBooking,
        flightBookingEmailTemplate
      );
    }

    // 5. Return success to customer
    res.json({
      success: true,
      message: 'Flight booked! Check your email for details.'
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: 'Booking failed. Please try again.'
    });
  }
});

Best Practices

  1. Cache Package Data: Cache package information for short periods to reduce API calls
  2. Clear Presentation: Display package options clearly with size, validity, and price
  3. Error Handling: Implement fallbacks if package fetching fails
  4. Email Templates: Create clear instructions for eSIM activation in emails
  5. Promo Code Storage: Securely store promo codes for customer service purposes

Monitoring and Support

Monitor your integration using:

  1. Package selection rates
  2. Booking success rates
  3. Promo code redemption rates
  4. Customer support inquiries

Contact support@hubbyesim.com for:

  • Custom package configurations
  • Integration support
  • API optimization

Next Steps

  1. Set up your API credentials
  2. Implement error handling