Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/paynow-gg/typescript-sdk/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Products API allows you to retrieve product information for display in your storefront. It provides endpoints to list all products and fetch individual product details.
Product operations do not require authentication, but providing a customer token will enable personalized pricing and trial eligibility checks.

Get Products

Retrieves the available products from your store. Supports filtering by tags and currency selection.
storefront.products.getStorefrontProducts(config?)

Parameters

config
object
Configuration object for the request

Returns

Returns an array of StorefrontProductDto objects. See Product Object for details.

Example

import { createStorefrontClient } from '@paynow-gg/sdk';

const storefront = createStorefrontClient('store-id');

// Get all products
const { data: products } = await storefront.products.getStorefrontProducts();

console.log(`Found ${products.length} products`);
products.forEach(product => {
  console.log(`${product.name}: ${product.price} ${product.currency}`);
});

// Get products filtered by tag
const { data: vipProducts } = await storefront.products.getStorefrontProducts({
  params: {
    tag: ['vip', 'premium']
  }
});

// Get products in specific currency
const { data: productsEur } = await storefront.products.getStorefrontProducts({
  params: {
    currency: 'eur'
  }
});

// Get products with customer IP for accurate VAT
const { data: productsWithVat } = await storefront.products.getStorefrontProducts({
  headers: {
    'x-paynow-customer-ip': '203.0.113.42',
    'x-paynow-customer-countrycode': 'DE'
  }
});

// Get products with multiple filters
const { data: filteredProducts } = await storefront.products.getStorefrontProducts({
  params: {
    tag: ['packages'],
    currency: 'usd'
  },
  headers: {
    'x-paynow-customer-ip': customerIp
  }
});

Get Product by ID or Slug

Retrieves a single product by its ID or URL-friendly slug.
storefront.products.getStorefrontProductByIdOrSlug(config)

Parameters

config
object
required
Configuration object for the request

Returns

Returns a StorefrontProductDto object. See Product Object for details.

Example

// Get product by ID
const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: {
    idOrSlug: '411486491630370816'
  }
});

console.log(product.name);
console.log(product.description);

// Get product by slug
const { data: productBySlug } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: {
    idOrSlug: 'premium-membership'
  }
});

// Get product with specific currency
const { data: productEur } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: {
    idOrSlug: 'premium-membership'
  },
  params: {
    currency: 'eur'
  }
});

// Get product with customer IP for pricing
const { data: productWithPricing } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: {
    idOrSlug: 'premium-membership'
  },
  headers: {
    'x-paynow-customer-ip': '203.0.113.42',
    'x-paynow-customer-countrycode': 'US'
  }
});

Product Object

The StorefrontProductDto object contains:
id
string
The product’s unique identifier
store_id
string
The store’s unique identifier
version_id
string
The product version identifier
slug
string
The unique URL-friendly slug for the product (e.g., “premium-game-package”)
name
string
The display name of the product
description
string
The detailed description of the product
image_url
string
The URL to the product image
price
number
The price of the product in the smallest currency unit (e.g., cents). Example: 1999 for $19.99
currency
string
The ISO three-letter lowercase currency code (e.g., usd, eur, gbp)
label
string
The display label for the product (e.g., “Best Value”)
sort_order
number
The sort order for displaying the product
enabled_at
string
The date and time when the product becomes enabled (ISO 8601 format)
enabled_until
string
The date and time until which the product remains enabled (ISO 8601 format)
allow_one_time_purchase
boolean
Indicates whether one-time purchases are allowed
allow_subscription
boolean
Indicates whether subscription purchases are allowed
subscription_interval_value
number
The subscription interval value (e.g., 1 for “1 month”)
subscription_interval_scale
string
The subscription interval scale (“day”, “week”, “month”, “year”)
remove_after_enabled
boolean
Indicates whether automatic removal is enabled
remove_after_time_value
number
The time value for automatic removal
remove_after_time_scale
string
The time scale for automatic removal (“day”, “week”, “month”)
single_game_server_only
boolean
Indicates whether the product is limited to a single game server
is_gifting_disabled
boolean
Indicates whether gifting is disabled for this product
is_gift_cards_disabled
boolean
Indicates whether gift cards are disabled for the product
is_coupons_disabled
boolean
Indicates whether coupons are disabled for the product
Indicates whether affiliate links are disabled for the product
pricing
object
Detailed pricing information including sales, discounts, and VAT rates
stock
object
Stock status information
trial
object
Trial period information
tags
array
The tags associated with the product for categorization
gameservers
array
The game servers associated with the product
custom_variables
array
Custom variables that can be configured during purchase
deliverable_actions
object
Actions to perform when the product is delivered
metadata
object
Additional metadata for the product
created_at
string
The date and time when the product was created (ISO 8601 format)
updated_at
string
The date and time when the product was last updated (ISO 8601 format)

Use Cases

Display all products with filtering:
async function loadProducts(tagFilter?: string[]) {
  const { data: products } = await storefront.products.getStorefrontProducts({
    params: tagFilter ? { tag: tagFilter } : undefined,
    headers: {
      'x-paynow-customer-ip': getCustomerIp(),
      'x-paynow-customer-countrycode': getCustomerCountry()
    }
  });
  
  return products.map(product => ({
    id: product.id,
    name: product.name,
    price: product.pricing?.price_final || product.price,
    originalPrice: product.pricing?.price_original,
    currency: product.currency,
    image: product.image_url,
    onSale: product.pricing?.active_sale != null
  }));
}
Show detailed product information:
async function loadProductDetails(slug: string) {
  const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
    path: { idOrSlug: slug },
    headers: {
      'x-paynow-customer-ip': getCustomerIp(),
      'x-paynow-customer-countrycode': getCustomerCountry()
    }
  });
  
  return {
    ...product,
    canPurchase: product.stock?.available_to_purchase ?? true,
    hasCustomization: product.custom_variables.length > 0,
    requiresGameServer: product.single_game_server_only,
    subscriptionInfo: product.allow_subscription ? {
      interval: product.subscription_interval_value,
      scale: product.subscription_interval_scale,
      trialAvailable: product.trial.enabled && product.trial.eligible
    } : null
  };
}
Show prices with VAT information:
async function displayProductPrice(productId: string) {
  const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
    path: { idOrSlug: productId },
    headers: {
      'x-paynow-customer-ip': getCustomerIp(),
      'x-paynow-customer-countrycode': getCustomerCountry()
    }
  });
  
  const price = product.pricing?.price_final || product.price;
  const vatRate = product.pricing?.vat_rate;
  
  return {
    price: price / 100, // Convert cents to dollars
    currency: product.currency,
    vatInfo: vatRate ? {
      percentage: vatRate.percentage,
      abbreviation: vatRate.vat_abbreviation,
      country: vatRate.country_name
    } : null
  };
}
Filter products using tags:
async function getProductsByCategory(category: string) {
  // First get all tags to find the category tag
  const { data: tags } = await storefront.tags.getStorefrontTags();
  const categoryTag = tags.find(t => t.slug === category);
  
  if (!categoryTag) {
    throw new Error('Category not found');
  }
  
  // Get products with that tag
  const { data: products } = await storefront.products.getStorefrontProducts({
    params: {
      tag: [category]
    }
  });
  
  return products;
}

Best Practices

When displaying products to customers, include IP and country headers to ensure accurate VAT calculation and regional pricing:
const { data: products } = await storefront.products.getStorefrontProducts({
  headers: {
    'x-paynow-customer-ip': req.ip,
    'x-paynow-customer-countrycode': req.countryCode
  }
});
Always check the stock status before allowing purchases:
const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: { idOrSlug: productId }
});

if (!product.stock?.available_to_purchase) {
  // Show "Out of Stock" message
  return;
}

// Proceed with purchase
For products with custom variables, ensure you collect all required values:
const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: { idOrSlug: productId }
});

const requiredVariables = product.custom_variables.filter(cv => {
  // Check if variable is required (no default value)
  return !cv.options.some(opt => opt.is_default);
});

// Collect values for all required variables before checkout
Show original and sale prices when applicable:
const { data: product } = await storefront.products.getStorefrontProductByIdOrSlug({
  path: { idOrSlug: productId }
});

const hasDiscount = product.pricing?.price_final !== product.pricing?.price_original;

return (
  <div>
    {hasDiscount && (
      <span className="line-through">
        {formatPrice(product.pricing.price_original, product.currency)}
      </span>
    )}
    <span className="price">
      {formatPrice(product.pricing?.price_final || product.price, product.currency)}
    </span>
  </div>
);