Quickstart

Get up and running with the Products V2 API in minutes.

What you'll learn

In this quickstart, you'll learn how to access and retrieve travel product information using the Products V2 API. We'll show you how to:

  • Retrieve and filter products
  • Get specific product details
  • Handle API responses effectively

Prerequisites

Before you start, you'll need:

  • An API access token with Products scope (get API access)
  • Basic knowledge of REST APIs and JSON

Step 1: Retrieve your first products

Let's start by retrieving travel products. Here's how to get a list of available products:

Get
// Set up your API request
const apiKey = 'API_KEY';
const apiUrl = 'https://api.joinsherpa.io/v2/products';

// Make the API call to get all products
fetch(apiUrl, {
  method: 'GET',
  headers: {
    'x-api-key': `${apiKey}`,
  },
})
  .then((response) => response.json())
  .then((data) => {
    console.log('Products retrieved:', data);
    displayProducts(data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });
🔑 Authentication Security

Never expose your API key in client-side code. In production, make API calls from your backend server and use environment variables to store your API key securely.

Step 2: Understanding the response

The API returns a detailed product object with comprehensive information about each travel product:

Product
{
  "name": "Turkey eVisa",
  "shortName": "Turkey eVisa",
  "description": "Electronic visa for Turkey tourism and business travel",
  "programId": "turkey-evisa",
  "productId": "turkey-evisa-tourism",
  "status": "ACTIVE",
  "type": "visa",
  "subType": {
    "value": "E_VISA",
    "label": "Electronic Visa"
  },
  "provider": {
    "value": "SHERPA",
    "label": "Sherpa"
  },
  "numberOfEntries": {
    "value": "SINGLE",
    "label": "Single Entry"
  },
  "travelPurposes": [
    {
      "value": "TOURISM",
      "label": "Tourism"
    },
    {
      "value": "BUSINESS_VISITOR",
      "label": "Business Visitor"
    }
  ],
  "destinations": [
    {
      "value": "TUR",
      "label": "Turkey"
    }
  ],
  "eligibleNationalities": [
    {
      "value": "USA",
      "label": "United States"
    },
    {
      "value": "CAN",
      "label": "Canada"
    },
    {
      "value": "GBR",
      "label": "United Kingdom"
    }
  ],
  "pricing": {
    "price": 75.00,
    "currency": "USD",
    "breakdown": [
      {
        "type": "GOVERNMENT_FEE",
        "price": 50.00,
        "label": "Government Fee"
      },
      {
        "type": "APPLICATION_SERVICE_FEE",
        "price": 25.00,
        "label": "Application Service Fee"
      }
    ]
  },
  "validity": {
    "value": 180,
    "unit": "DAYS",
    "startsFrom": "APPROVAL",
    "label": "180 days from approval"
  },
  "processingTime": {
    "value": 24,
    "unit": "HOURS",
    "label": "24 hours"
  },
  "lengthOfStay": {
    "value": 90,
    "unit": "DAYS",
    "label": "90 days"
  }
}

Step 3: Filter and search products

Now let's retrieve products with filtering options:

Retrieve
// Get all active products for Turkey
const filterParams = new URLSearchParams({
  status: 'ACTIVE',
  destination: 'TUR',
  currency: 'USD',
  consolidateProducts: 'false'
});

fetch(`https://api.joinsherpa.io/v2/products?${filterParams}`, {
  method: 'GET',
  headers: {
    'x-api-key': `${apiKey}`,
  },
})
  .then((response) => response.json())
  .then((data) => {
    console.log('Products found:', data);
    displayProducts(data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

// Get a specific product by ID
fetch('https://api.joinsherpa.io/v2/products/turkey-evisa-tourism', {
  method: 'GET',
  headers: {
    'x-api-key': `${apiKey}`,
  },
})
  .then((response) => response.json())
  .then((data) => {
    console.log('Product details:', data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

Step 4: Get specific product details

Retrieve detailed information for a specific product:

Get
// Get a specific product by its ID
const productId = 'turkey-evisa-tourism';

fetch(`https://api.joinsherpa.io/v2/products/${productId}`, {
  method: 'GET',
  headers: {
    'x-api-key': `${apiKey}`,
  },
})
  .then((response) => response.json())
  .then((data) => {
    console.log('Product details:', data);
    displayProductDetails(data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

Complete Example: Product Information Dashboard

Here's a complete HTML example that demonstrates all the key features for accessing product information:

Complete
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Products V2 API - Quickstart</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .product { border: 1px solid #ddd; padding: 15px; margin: 10px 0; border-radius: 5px; }
        .product h3 { margin-top: 0; color: #206ee8; }
        .price { font-weight: bold; color: #28a745; }
        .status { padding: 3px 8px; border-radius: 3px; font-size: 12px; }
        .status.ACTIVE { background: #d4edda; color: #155724; }
        .status.INACTIVE { background: #f8d7da; color: #721c24; }
        button { background: #206ee8; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }
        button:hover { background: #0b3fd8; }
        .error { color: #dc3545; background: #f8d7da; padding: 10px; border-radius: 4px; margin: 10px 0; }
        .success { color: #155724; background: #d4edda; padding: 10px; border-radius: 4px; margin: 10px 0; }
    </style>
</head>
<body>
    <h1>Products V2 API - Quickstart Demo</h1>
    
    <div id="controls">
        <button onclick="loadProducts()">Load All Products</button>
        <button onclick="loadProductById()">Load Product by ID</button>
    </div>
    
    <div id="status"></div>
    <div id="products"></div>

    <script>
        // Configuration
        const API_KEY = 'YOUR_API_KEY_HERE';
        const API_BASE = 'https://api.joinsherpa.io/v2/products';
        
        // Helper function to show status messages
        function showStatus(message, type = 'success') {
            const statusDiv = document.getElementById('status');
            statusDiv.innerHTML = `<div class="${type}">${message}</div>`;
            setTimeout(() => statusDiv.innerHTML = '', 5000);
        }
        
        // Helper function to display products
        function displayProducts(products) {
            const container = document.getElementById('products');
            if (!Array.isArray(products)) {
                products = [products];
            }
            
            container.innerHTML = products.map(product => `
                <div class="product">
                    <h3>${product.name}</h3>
                    <p><strong>Product ID:</strong> ${product.productId}</p>
                    <p><strong>Status:</strong> <span class="status ${product.status}">${product.status}</span></p>
                    <p><strong>Type:</strong> ${product.subType?.label || product.subType}</p>
                    <p><strong>Destinations:</strong> ${product.destinations?.map(d => d.label || d).join(', ')}</p>
                    <p><strong>Eligible Nationalities:</strong> ${product.eligibleNationalities?.map(n => n.label || n).join(', ')}</p>
                    <p class="price">Price: ${product.pricing?.currency || 'USD'} ${product.pricing?.price || 'N/A'}</p>
                    ${product.validity ? `<p><strong>Validity:</strong> ${product.validity.label || product.validity.value + ' ' + product.validity.unit}</p>` : ''}
                    ${product.processingTime ? `<p><strong>Processing Time:</strong> ${product.processingTime.label || product.processingTime.value + ' ' + product.processingTime.unit}</p>` : ''}
                </div>
            `).join('');
        }
        
        
        
        // Load all products
        async function loadProducts() {
            try {
                const response = await fetch(`${API_BASE}?status=ACTIVE&currency=USD`, {
                    headers: {
                        'x-api-key': `${API_KEY}`,
                    },
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                
                const data = await response.json();
                showStatus('Products loaded successfully!');
                displayProducts(data);
            } catch (error) {
                console.error('Error loading products:', error);
                showStatus(`Error loading products: ${error.message}`, 'error');
            }
        }
        
        // Load product by ID
        async function loadProductById() {
            const productId = prompt('Enter product ID:');
            if (!productId) return;
            
            try {
                const response = await fetch(`${API_BASE}/${productId}?currency=USD`, {
                    headers: {
                        'x-api-key': `${API_KEY}`,
                    },
                });
                
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                
                const data = await response.json();
                showStatus('Product loaded successfully!');
                displayProducts(data);
            } catch (error) {
                console.error('Error loading product:', error);
                showStatus(`Error loading product: ${error.message}`, 'error');
            }
        }
        
    </script>
</body>
</html>

Understanding the response structure

The Products V2 API returns rich, structured data with several key sections:

Product Information

  • Basic Details: Name, description, product ID, and status
  • Categorization: Type, subtype, and provider information
  • Targeting: Destinations, eligible nationalities, and travel purposes

Pricing Information

  • Total Price: Calculated total with currency
  • Price Breakdown: Detailed breakdown by fee type
  • Currency Support: Multi-currency pricing with real-time conversion

Timing Information

  • Validity Period: How long the product is valid
  • Processing Time: Expected processing duration
  • Length of Stay: Maximum stay duration
  • Application Deadlines: When applications must be submitted

Metadata

  • Localization: Multi-language support for descriptions
  • Affiliate Targeting: Specific affiliate inclusion/exclusion
📋 Response Variations

The API response structure can vary depending on the endpoint and parameters used. Some responses may include additional metadata, while others focus on specific product details. The examples above handle the most common response patterns.

Next Steps

Now that you've completed the quickstart, you're ready to:

  1. Review Use Cases: See practical examples in our Use Cases section
  2. Check Endpoint Details: Dive deeper into specific endpoints in our Endpoints documentation
  3. Read the FAQ: Find answers to common questions in our Products V2 FAQ

Common Patterns

Error Handling

Always implement proper error handling for production applications:

try {
  const response = await fetch(apiUrl, options);
  
  if (!response.ok) {
    const errorData = await response.json();
    throw new Error(`API Error: ${errorData.message}`);
  }
  
  const data = await response.json();
  return data;
} catch (error) {
  console.error('API call failed:', error);
  // Handle error appropriately
}