> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Loading Product Catalog

> Fetch and cache gift card products organized by category

## Overview

The catalog endpoint returns all available gift cards and digital products organized by categories like Gaming Cards, Streaming Services, etc. Products should be cached to minimize API calls since the catalog changes infrequently.

<Info>
  Cache catalog data for **at least 24 hours**. Products are added/removed
  rarely.
</Info>

## API Reference

<Card title="GET /v3/gift-cards/catalog" icon="list" href="/en/api-reference/gift-cards/get-catalog">
  Complete endpoint documentation
</Card>

## Basic Catalog Loading

<CodeGroup>
  ```javascript Node.js theme={null}
  async function loadCatalog() {
    const response = await fetch(
      "https://api.oneclickdz.com/v3/gift-cards/catalog",
      {
        headers: {
          "X-Access-Token": process.env.API_KEY,
        },
      }
    );

    if (!response.ok) {
      throw new Error(`Failed to load catalog: ${response.status}`);
    }

    const result = await response.json();
    return result.data;
  }

  // Usage
  const catalog = await loadCatalog();
  console.log(`Total categories: ${catalog.categories.length}`);
  console.log(
    `Total products: ${catalog.categories.reduce(
      (sum, cat) => sum + cat.products.length,
      0
    )}`
  );
  ```

  ```python Python theme={null}
  import requests
  import os

  def load_catalog():
      response = requests.get(
          'https://api.oneclickdz.com/v3/gift-cards/catalog',
          headers={'X-Access-Token': os.getenv('API_KEY')}
      )

      response.raise_for_status()
      return response.json()['data']

  # Usage
  catalog = load_catalog()
  total_products = sum(len(cat['products']) for cat in catalog['categories'])
  print(f"Loaded {len(catalog['categories'])} categories with {total_products} products")
  ```

  ```php PHP theme={null}
  <?php

  function loadCatalog($apiKey) {
      $ch = curl_init('https://api.oneclickdz.com/v3/gift-cards/catalog');
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'X-Access-Token: ' . $apiKey
      ]);

      $response = curl_exec($ch);
      $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);

      if ($httpCode !== 200) {
          throw new Exception("Failed to load catalog: " . $httpCode);
      }

      $result = json_decode($response, true);
      return $result['data'];
  }

  // Usage
  $catalog = loadCatalog(getenv('API_KEY'));
  echo "Total categories: " . count($catalog['categories']) . "\n";
  ?>
  ```

  ```bash cURL theme={null}
  curl https://api.oneclickdz.com/v3/gift-cards/catalog \
    -H "X-Access-Token: YOUR_API_KEY"
  ```
</CodeGroup>

## Response Structure

```json theme={null}
{
  "success": true,
  "data": {
    "categories": [
      {
        "name": "Gaming Cards",
        "products": [
          {
            "id": "507f1f77bcf86cd799439011",
            "title": "PlayStation Network",
            "enabled": true,
            "region": "dz"
          },
          {
            "id": "507f1f77bcf86cd799439012",
            "title": "Google Play Gift Card",
            "enabled": true
          }
        ]
      },
      {
        "name": "Streaming Services",
        "products": [
          {
            "id": "507f1f77bcf86cd799439014",
            "title": "Netflix Gift Card",
            "enabled": true
          }
        ]
      }
    ]
  },
  "meta": {
    "totalCategories": 8,
    "totalProducts": 127
  }
}
```

## Caching Implementation

<CodeGroup>
  ```javascript Node.js theme={null}
  class CatalogCache {
    constructor(ttlMinutes = 10) {
      this.data = null;
      this.timestamp = 0;
      this.ttl = ttlMinutes * 60 * 1000;
    }

    async get() {
      const now = Date.now();

      // Return cached if still valid
      if (this.data && now - this.timestamp < this.ttl) {
        console.log("Returning cached catalog");
        return this.data;
      }

      // Fetch fresh data
      console.log("Fetching fresh catalog");
      const response = await fetch(
        "https://api.oneclickdz.com/v3/gift-cards/catalog",
        {
          headers: { "X-Access-Token": process.env.API_KEY },
        }
      );

      this.data = await response.json();
      this.timestamp = now;

      return this.data;
    }

    invalidate() {
      this.data = null;
      this.timestamp = 0;
    }
  }

  // Usage
  const cache = new CatalogCache(10); // 24 hours TTL

  // First call - fetches from API
  const catalog1 = await cache.get();

  // Second call within 24 hours - returns cached
  const catalog2 = await cache.get();

  // Force refresh
  cache.invalidate();
  const catalog3 = await cache.get(); // Fetches fresh
  ```

  ```python Python theme={null}
  from datetime import datetime, timedelta
  import requests
  import os

  class CatalogCache:
      def __init__(self, ttl_minutes=10):
          self.data = None
          self.timestamp = None
          self.ttl = timedelta(minutes=ttl_minutes)

      def get(self):
          now = datetime.now()

          # Return cached if still valid
          if self.data and self.timestamp and (now - self.timestamp) < self.ttl:
              print('Returning cached catalog')
              return self.data

          # Fetch fresh data
          print('Fetching fresh catalog')
          response = requests.get(
              'https://api.oneclickdz.com/v3/gift-cards/catalog',
              headers={'X-Access-Token': os.getenv('API_KEY')}
          )
          response.raise_for_status()

          self.data = response.json()
          self.timestamp = now

          return self.data

      def invalidate(self):
          self.data = None
          self.timestamp = None

  # Usage
  cache = CatalogCache(ttl_minutes=10)

  # First call - fetches from API
  catalog1 = cache.get()

  # Second call within 24 hours - returns cached
  catalog2 = cache.get()

  # Force refresh
  cache.invalidate()
  catalog3 = cache.get()
  ```

  ```php PHP theme={null}
  <?php

  class CatalogCache {
      private $data = null;
      private $timestamp = 0;
      private $ttl;
      private $apiKey;

      public function __construct($apiKey, $ttlMinutes = 10) {
          $this->apiKey = $apiKey;
          $this->ttl = $ttlMinutes * 60;
      }

      public function get() {
          $now = time();

          // Return cached if still valid
          if ($this->data !== null && ($now - $this->timestamp) < $this->ttl) {
              error_log('Returning cached catalog');
              return $this->data;
          }

          // Fetch fresh data
          error_log('Fetching fresh catalog');
          $ch = curl_init('https://api.oneclickdz.com/v3/gift-cards/catalog');
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_HTTPHEADER, [
              'X-Access-Token: ' . $this->apiKey
          ]);

          $response = curl_exec($ch);
          curl_close($ch);

          $this->data = json_decode($response, true);
          $this->timestamp = $now;

          return $this->data;
      }

      public function invalidate() {
          $this->data = null;
          $this->timestamp = 0;
      }
  }

  // Usage
  $cache = new CatalogCache(getenv('API_KEY'), 10);

  // First call - fetches from API
  $catalog1 = $cache->get();

  // Second call within 24 hours - returns cached
  $catalog2 = $cache->get();

  // Force refresh
  $cache->invalidate();
  $catalog3 = $cache->get();
  ?>
  ```
</CodeGroup>

## Filtering Products

Only show enabled products to customers:

<CodeGroup>
  ```javascript Node.js theme={null}
  function getEnabledProducts(catalog) {
    const enabled = [];

    for (const category of catalog.categories) {
      const enabledInCategory = category.products.filter((p) => p.enabled);

      if (enabledInCategory.length > 0) {
        enabled.push({
          categoryName: category.name,
          products: enabledInCategory,
        });
      }
    }

    return enabled;
  }

  // Usage
  const catalog = await cache.get();
  const enabledProducts = getEnabledProducts(catalog.data);
  console.log("Enabled products:", JSON.stringify(enabledProducts, null, 2));
  ```

  ```python Python theme={null}
  def get_enabled_products(catalog):
      enabled = []

      for category in catalog['categories']:
          enabled_in_category = [p for p in category['products'] if p['enabled']]

          if enabled_in_category:
              enabled.append({
                  'categoryName': category['name'],
                  'products': enabled_in_category
              })

      return enabled

  # Usage
  catalog = cache.get()
  enabled_products = get_enabled_products(catalog['data'])
  print(f"Found {len(enabled_products)} categories with enabled products")
  ```

  ```php PHP theme={null}
  <?php

  function getEnabledProducts($catalog) {
      $enabled = [];

      foreach ($catalog['categories'] as $category) {
          $enabledInCategory = array_filter(
              $category['products'],
              function($p) { return $p['enabled']; }
          );

          if (!empty($enabledInCategory)) {
              $enabled[] = [
                  'categoryName' => $category['name'],
                  'products' => array_values($enabledInCategory)
              ];
          }
      }

      return $enabled;
  }

  // Usage
  $catalog = $cache->get();
  $enabledProducts = getEnabledProducts($catalog['data']);
  echo "Enabled categories: " . count($enabledProducts) . "\n";
  ?>
  ```
</CodeGroup>

## Region Filtering

Filter products by region if targeting specific markets:

```javascript theme={null}
function filterByRegion(catalog, region = "dz") {
  return catalog.categories
    .map((category) => ({
      ...category,
      products: category.products.filter(
        (p) => p.enabled && (!p.region || p.region === region)
      ),
    }))
    .filter((cat) => cat.products.length > 0);
}

// Usage
const algerianProducts = filterByRegion(catalog.data, "dz");
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Handle Errors Gracefully" icon="triangle-exclamation">
    Fall back to cached data if API is temporarily unavailable
  </Card>

  <Card title="Organize by Category" icon="folder-tree">
    Use category structure for better user experience
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="Check Products" icon="magnifying-glass" href="/en/gift-card-guides/2-checking-products">
    Get pricing and stock for selected products
  </Card>

  {" "}

  <Card title="Place Orders" icon="cart-shopping" href="/en/gift-card-guides/3-placing-orders">
    Submit orders with validation
  </Card>

  {" "}

  <Card title="API Reference" icon="book" href="/en/api-reference/gift-cards/get-catalog">
    Complete endpoint documentation
  </Card>

  {" "}

  <Card title="Overview" icon="book-open" href="/en/gift-card-guides/overview">
    Back to integration overview
  </Card>

  {" "}

  <Card title="Track Status" icon="chart-line" href="/en/gift-card-guides/4-status-tracking">
    Monitor order fulfillment
  </Card>

  <Card title="Secure Delivery" icon="lock" href="/en/gift-card-guides/5-secure-delivery">
    Encrypt and deliver cards
  </Card>
</CardGroup>
