JAVASCRIPT

Client-Side API Version Selection with Headers

Learn to interact with different versions of a REST API by dynamically setting the `Accept` header or a custom `X-API-Version` header in your JavaScript HTTP requests.

// Function to make API requests with a specified version
async function callApi(url, version, options = {}) {
  const headers = {
    'Content-Type': 'application/json',
    ...options.headers
  };

  // Common patterns for API versioning via headers:

  // 1. Custom Header (e.g., X-API-Version)
  if (version) {
    headers['X-API-Version'] = version;
  }

  // 2. Accept Header (Vendor-specific media type)
  // e.g., 'Accept': 'application/vnd.myapi.v2+json'
  // if (version) {
  //   headers['Accept'] = `application/vnd.myapi.v${version}+json`;
  // }

  try {
    const response = await fetch(url, { ...options, headers });

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({ message: response.statusText }));
      throw new Error(`API call failed (v${version}): ${response.status} - ${errorData.message}`);
    }

    return await response.json();
  } catch (error) {
    console.error(`Error calling API (v${version}):`, error);
    throw error;
  }
}

// --- Example Usage ---
// Assuming a hypothetical API that uses 'X-API-Version' header
// and returns different data structures or logic based on the version.

// (async () => {
//   try {
//     // Fetch data using API Version 1
//     console.log('Fetching data with API Version 1...');
//     const dataV1 = await callApi('/api/products', '1');
//     console.log('API V1 Response:', dataV1);
//     // Expected: { id: 'prod-abc', name: 'Widget', price: 29.99 }

//     // Fetch data using API Version 2 (might have different fields or formats)
//     console.log('
Fetching data with API Version 2...');
//     const dataV2 = await callApi('/api/products', '2');
//     console.log('API V2 Response:', dataV2);
//     // Expected: { product_id: 'prod-abc', product_name: 'Super Widget', current_price: 34.50, currency: 'USD' }

//     // Example with an API that doesn't exist, or a version not supported
//     console.log('
Fetching data with unsupported API Version...');
//     await callApi('/api/products', '99').catch(e => console.error('Caught error for V99:', e.message));

//   } catch (error) {
//     console.error('An unhandled error occurred:', error);
//   }
// })();

// --- Hypothetical Server-Side Endpoint (Node.js with Express) to demonstrate versioning ---
/*
const express = require('express');
const app = express();
const PORT = 3000;

app.get('/api/products', (req, res) => {
    const apiVersion = req.headers['x-api-version'] || '1'; // Default to V1

    if (apiVersion === '1') {
        res.json({ id: 'prod-abc', name: 'Widget', price: 29.99 });
    } else if (apiVersion === '2') {
        res.json({ product_id: 'prod-abc', product_name: 'Super Widget', current_price: 34.50, currency: 'USD' });
    } else {
        res.status(400).json({ error: `Unsupported API version: ${apiVersion}` });
    }
});

app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));
*/
How it works: API versioning is crucial for evolving web services while maintaining backward compatibility. This JavaScript snippet shows how a client can dynamically specify the desired API version using HTTP request headers. The `callApi` function accepts a `version` parameter, which it then adds to the request headers. Two common header-based versioning strategies are demonstrated: using a custom header like `X-API-Version` or using the `Accept` header with a vendor-specific media type (e.g., `application/vnd.myapi.v2+json`). Your backend API would then inspect these headers to determine which version of the resource or logic to serve. This allows different clients to interact with the API using their preferred or compatible versions simultaneously.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs