Dynamic Pricing Information

Access real-time pricing information with multi-currency support and price change tracking using the Products V2 API.

Overview

Dynamic pricing information allows you to access accurate, up-to-date pricing information across your product catalog. The Products V2 API provides powerful tools for accessing real-time pricing information, multi-currency support, and price change tracking.

Key Features

  • Real-time Information: Access current prices across all products
  • Multi-currency Support: Handle pricing in multiple currencies
  • Price Change History: Access price change history and tracking
  • Price Change Monitoring: Monitor and access all price changes
  • Bulk Price Access: Access multiple product prices simultaneously
  • Price Data Validation: Ensure price data integrity

Implementation Examples

1. Real-time Price Information

Access real-time price information for individual products:

Real-time
class PriceInformationAccessor {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.joinsherpa.io/v2/products';
  }

  // Get product pricing information
  async getProductPricing(productId, currency = 'USD') {
    try {
      const response = await fetch(`${this.baseUrl}/${productId}?currency=${currency}`, {
        method: 'GET',
        headers: {
          'x-api-key': `${this.apiKey}`,
        },
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(`API Error: ${errorData.message}`);
      }

      const product = await response.json();
      console.log(`Pricing for product ${productId}:`, product.pricing);
      return product.pricing;
    } catch (error) {
      console.error(`Failed to get pricing for ${productId}:`, error.message);
      throw error;
    }
  }

  // Get government fee information
  async getGovernmentFee(productId, currency = 'USD') {
    const pricing = await this.getProductPricing(productId, currency);
    return pricing.breakdown?.find(fee => fee.type === 'GOVERNMENT_FEE');
  }

  // Get service fee information
  async getServiceFee(productId, currency = 'USD') {
    const pricing = await this.getProductPricing(productId, currency);
    return pricing.breakdown?.find(fee => fee.type === 'APPLICATION_SERVICE_FEE');
  }

  // Get all fee types
  async getAllFees(productId, currency = 'USD') {
    const pricing = await this.getProductPricing(productId, currency);
    return pricing.breakdown || [];
  }
}

// Usage examples
const priceAccessor = new PriceInformationAccessor('YOUR_API_KEY');

// Get government fee information
priceAccessor.getGovernmentFee('turkey-evisa-tourism', 'USD')
  .then(fee => {
    console.log('Government fee:', fee);
  });

// Get service fee information
priceAccessor.getServiceFee('turkey-evisa-tourism', 'USD')
  .then(fee => {
    console.log('Service fee:', fee);
  });

// Get all fees
priceAccessor.getAllFees('turkey-evisa-tourism', 'USD')
  .then(fees => {
    console.log('All fees:', fees);
  });

2. Bulk Price Information Access

Access price information for multiple products:

Bulk
class BulkPriceAccessor {
  constructor(priceAccessor) {
    this.priceAccessor = priceAccessor;
  }

  // Get government fees for multiple products
  async getGovernmentFees(productIds, currency = 'USD') {
    const results = [];
    
    for (const productId of productIds) {
      try {
        const fee = await this.priceAccessor.getGovernmentFee(productId, currency);
        results.push({ 
          success: true, 
          productId, 
          fee 
        });
      } catch (error) {
        results.push({ 
          success: false, 
          productId, 
          error: error.message 
        });
      }
    }
    
    return results;
  }

  // Get service fees for multiple products
  async getServiceFees(productIds, currency = 'USD') {
    const results = [];
    
    for (const productId of productIds) {
      try {
        const fee = await this.priceAccessor.getServiceFee(productId, currency);
        results.push({ 
          success: true, 
          productId, 
          fee 
        });
      } catch (error) {
        results.push({ 
          success: false, 
          productId, 
          error: error.message 
        });
      }
    }
    
    return results;
  }

  // Get all fees for multiple products
  async getAllFeesForProducts(productIds, currency = 'USD') {
    const results = [];
    
    for (const productId of productIds) {
      try {
        const fees = await this.priceAccessor.getAllFees(productId, currency);
        results.push({ 
          success: true, 
          productId, 
          fees 
        });
      } catch (error) {
        results.push({ 
          success: false, 
          productId, 
          error: error.message 
        });
      }
    }
    
    return results;
  }
}

// Usage examples
const bulkPriceAccessor = new BulkPriceAccessor(priceAccessor);

// Get government fees for multiple products
const productIds = ['turkey-evisa-tourism', 'turkey-evisa-business', 'uk-eta-tourism'];

bulkPriceAccessor.getGovernmentFees(productIds, 'USD')
  .then(results => {
    console.log('Government fees for products:', results);
  });

// Get all fees for multiple products
bulkPriceAccessor.getAllFeesForProducts(productIds, 'USD')
  .then(results => {
    console.log('All fees for products:', results);
  });

3. Multi-currency Price Information

Access pricing information in multiple currencies:

Multi-currency
class MultiCurrencyPriceAccessor {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.joinsherpa.io/v2/products';
    this.exchangeRates = new Map();
  }

  // Get exchange rates (mock implementation)
  async getExchangeRates(baseCurrency = 'USD') {
    // In a real implementation, you would fetch from an exchange rate API
    const rates = {
      USD: 1.0,
      EUR: 0.85,
      GBP: 0.73,
      CAD: 1.25,
      AUD: 1.35,
      JPY: 110.0
    };
    
    this.exchangeRates.set(baseCurrency, rates);
    return rates;
  }

  // Convert price to different currency
  convertPrice(price, fromCurrency, toCurrency) {
    if (fromCurrency === toCurrency) return price;
    
    const rates = this.exchangeRates.get('USD');
    if (!rates) throw new Error('Exchange rates not loaded');
    
    // Convert to USD first, then to target currency
    const usdPrice = fromCurrency === 'USD' ? price : price / rates[fromCurrency];
    const targetPrice = toCurrency === 'USD' ? usdPrice : usdPrice * rates[toCurrency];
    
    return Math.round(targetPrice * 100) / 100;
  }

  // Get product pricing in specific currency
  async getProductPricingInCurrency(productId, currency) {
    const response = await fetch(`${this.baseUrl}/${productId}?currency=${currency}`, {
      headers: {
        'Authorization': `Bearer ${this.apiToken}`,
      },
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(`API Error: ${errorData.message}`);
    }

    const product = await response.json();
    return product.pricing;
  }

  // Get pricing in multiple currencies
  async getPricingInMultipleCurrencies(productId, currencies) {
    const results = [];
    
    for (const currency of currencies) {
      try {
        const pricing = await this.getProductPricingInCurrency(productId, currency);
        results.push({ 
          success: true, 
          currency, 
          pricing 
        });
      } catch (error) {
        results.push({ 
          success: false, 
          currency, 
          error: error.message 
        });
      }
    }
    
    return results;
  }

}

// Usage examples
const multiCurrencyAccessor = new MultiCurrencyPriceAccessor('YOUR_API_KEY');

// Load exchange rates
multiCurrencyAccessor.getExchangeRates()
  .then(rates => {
    console.log('Exchange rates loaded:', rates);
  });

// Get product pricing in EUR
multiCurrencyAccessor.getProductPricingInCurrency('turkey-evisa-tourism', 'EUR')
  .then(pricing => {
    console.log('Product pricing in EUR:', pricing);
  });

// Get pricing in multiple currencies
const currencies = ['USD', 'EUR', 'GBP', 'CAD'];

multiCurrencyAccessor.getPricingInMultipleCurrencies('turkey-evisa-tourism', currencies)
  .then(results => {
    console.log('Pricing in multiple currencies:', results);
  });

4. Price Change Monitoring

Monitor price changes and access price history:

Price
class PriceChangeMonitor {
  constructor(priceAccessor) {
    this.priceAccessor = priceAccessor;
    this.monitorInterval = null;
    this.isRunning = false;
  }

  // Start price monitoring
  startMonitoring(intervalMinutes = 60) {
    if (this.isRunning) {
      console.log('Price monitoring is already running');
      return;
    }

    this.isRunning = true;
    this.monitorInterval = setInterval(() => {
      this.performMonitoring();
    }, intervalMinutes * 60 * 1000);

    console.log(`Price monitoring started (every ${intervalMinutes} minutes)`);
  }

  // Stop price monitoring
  stopMonitoring() {
    if (this.monitorInterval) {
      clearInterval(this.monitorInterval);
      this.monitorInterval = null;
      this.isRunning = false;
      console.log('Price monitoring stopped');
    }
  }

  // Perform price monitoring
  async performMonitoring() {
    try {
      console.log('Starting price monitoring...');
      
      // Get products to monitor
      const productsToMonitor = await this.getProductsToMonitor();
      
      if (productsToMonitor.length === 0) {
        console.log('No products to monitor');
        return;
      }

      // Monitor prices for each product
      const results = [];
      for (const product of productsToMonitor) {
        try {
          const currentPricing = await this.priceAccessor.getProductPricing(product.productId);
          results.push({ success: true, productId: product.productId, pricing: currentPricing });
          }
        } catch (error) {
          results.push({ success: false, productId: product.productId, error: error.message });
        }
      }

      console.log('Price monitoring completed:', results);
      return results;
    } catch (error) {
      console.error('Price monitoring failed:', error);
      throw error;
    }
  }

  // Get products to monitor (mock implementation)
  async getProductsToMonitor() {
    // In a real implementation, you would check which products to monitor
    return [
      { productId: 'turkey-evisa-tourism', lastChecked: '2024-01-01' },
      { productId: 'turkey-evisa-business', lastChecked: '2024-01-01' }
    ];
  }

  // Manual price monitoring
  async manualMonitoring(productIds) {
    const results = [];
    
    for (const productId of productIds) {
      try {
        const currentPricing = await this.priceAccessor.getProductPricing(productId);
        results.push({ success: true, productId, pricing: currentPricing });
      } catch (error) {
        results.push({ success: false, productId, error: error.message });
      }
    }
    
    return results;
  }
}

// Usage examples
const priceMonitor = new PriceChangeMonitor(priceAccessor);

// Start automated monitoring (every hour)
priceMonitor.startMonitoring(60);

// Manual monitoring
priceMonitor.manualMonitoring(['turkey-evisa-tourism', 'turkey-evisa-business'])
  .then(results => {
    console.log('Manual monitoring results:', results);
  });

// Stop monitoring
// priceMonitor.stopMonitoring();



        // Compare pricing and detect changes
        const changes = this.detectPriceChanges(previousPricing, currentPricing);
        
        if (changes.length > 0) {
          const changeEvent = {
            productId,
            productName: product.name,
            timestamp: new Date().toISOString(),
            changes,
            previousPricing,
            currentPricing
          };

          // Store updated pricing
          this.priceHistory.set(productId, currentPricing);

          // Call callback with change event
          if (callback) {
            callback(changeEvent);
          }

          return changeEvent;
        }
      } else {
        // First time monitoring this product
        this.priceHistory.set(productId, currentPricing);
      }

      return null;
    } catch (error) {
      console.error(`Failed to monitor price changes for ${productId}:`, error);
      throw error;
    }
  }

  // Detect price changes between two pricing objects
  detectPriceChanges(previousPricing, currentPricing) {
    const changes = [];
    const previousBreakdown = previousPricing?.breakdown || [];
    const currentBreakdown = currentPricing?.breakdown || [];

    // Check for changes in existing fees
    previousBreakdown.forEach(prevFee => {
      const currentFee = currentBreakdown.find(fee => fee.type === prevFee.type);
      
      if (currentFee) {
        if (prevFee.price !== currentFee.price) {
          changes.push({
            type: 'PRICE_CHANGE',
            feeType: prevFee.type,
            previousPrice: prevFee.price,
            currentPrice: currentFee.price,
            change: currentFee.price - prevFee.price,
            changePercentage: ((currentFee.price - prevFee.price) / prevFee.price) * 100
          });
        }
      } else {
        changes.push({
          type: 'FEE_REMOVED',
          feeType: prevFee.type,
          previousPrice: prevFee.price
        });
      }
    });

    // Check for new fees
    currentBreakdown.forEach(currentFee => {
      const prevFee = previousBreakdown.find(fee => fee.type === currentFee.type);
      
      if (!prevFee) {
        changes.push({
          type: 'FEE_ADDED',
          feeType: currentFee.type,
          currentPrice: currentFee.price
        });
      }
    });

    return changes;
  }

  // Monitor multiple products
  async monitorMultipleProducts(productIds, callback) {
    const results = [];
    
    for (const productId of productIds) {
      try {
        const changeEvent = await this.monitorProductPriceChanges(productId, callback);
        if (changeEvent) {
          results.push(changeEvent);
        }
      } catch (error) {
        results.push({ 
          productId, 
          error: error.message 
        });
      }
    }
    
    return results;
  }

  // Get price history for a product
  getPriceHistory(productId) {
    return this.priceHistory.get(productId);
  }

  // Clear price history
  clearPriceHistory(productId) {
    if (productId) {
      this.priceHistory.delete(productId);
    } else {
      this.priceHistory.clear();
    }
  }
}

// Usage examples
const priceMonitor = new PriceChangeMonitor('YOUR_API_KEY');

// Monitor single product
priceMonitor.monitorProductPriceChanges('turkey-evisa-tourism', (changeEvent) => {
  console.log('Price change detected:', changeEvent);
  
  // Send notification, log to database, etc.
  if (changeEvent.changes.some(change => change.type === 'PRICE_CHANGE')) {
    console.log('Price changed for', changeEvent.productName);
  }
});

// Monitor multiple products
priceMonitor.monitorMultipleProducts(
  ['turkey-evisa-tourism', 'turkey-evisa-business'],
  (changeEvent) => {
    console.log('Price change detected:', changeEvent);
  }
);`} />

## Best Practices

### Price Update Strategy
- **Validation**: Always validate price data before updates
- **Atomic Updates**: Use atomic operations for price updates
- **Error Handling**: Implement robust error handling for failed updates
- **Rollback**: Maintain ability to rollback price changes

### Performance Optimization
- **Bulk Operations**: Use bulk updates for multiple products
- **Caching**: Cache price data to reduce API calls
- **Rate Limiting**: Respect API rate limits
- **Async Processing**: Use async operations for better performance

### Data Integrity
- **Consistency**: Ensure price consistency across all products
- **Validation**: Validate price data against business rules
- **Backup**: Regularly backup price data

### Monitoring and Alerting
- **Change Detection**: Monitor for unexpected price changes
- **Alerts**: Set up alerts for significant price changes
- **Logging**: Log all price update operations
- **Metrics**: Track price update performance and success rates

<InfoCard title="💡 Pricing Tips" color="blue">
  - Use bulk operations for efficient price updates
  - Implement price validation to prevent invalid updates
  - Monitor price changes for compliance
  - Use multi-currency support for global markets
</InfoCard>

<InfoCard title="🚀 Getting Started" color="green">
  Start with simple price updates and gradually implement more sophisticated
  features like bulk updates and automated synchronization.
</InfoCard>