Appearance
Products
API Type
eCommerce API - Uses API key in request body. See Authentication.
Load photobook products for a specific market with detailed specifications and pricing.
List Products
Retrieve all available photobook products for a market, including categories, pricing, and specifications.
Endpoint
POST https://{ecomm}.photobook.ai/api/v2/products/list-product.phpReplace {ecomm} with your assigned client identifier.
Example: https://yourclient.photobook.ai/api/v2/products/list-product.php
Authentication
See Authentication - eCommerce
Request Parameters
json
{
"env": "dev",
"key": "your-api-key",
"language": "en",
"os": "web",
"marketId": 0,
"printType": "photobook"
}| Parameter | Type | Required | Description |
|---|---|---|---|
env | string | Yes | Target environment: dev or prod |
key | string | Yes | Your programmatic access key |
language | string | No | First 2 characters of language code (e.g., en). Defaults to en |
os | string | Yes | Target platform. Use web for PWA |
v | integer | No | Version target. Fetches products tagged with this value and lower. Leave undefined if unsure |
schema | integer | No | Schema version for response structure. Leave undefined if unsure |
marketId | integer | No | Target market ID. Defaults to 0 (default market) |
printType | string | No | Product type filter. Use photobook (other types not yet supported) |
Response Structure
json
{
"baseUrl": "https://cdn.photobook.ai/products/",
"pricesIncludeTax": false,
"currency": {
"code": "USD",
"left": "$",
"right": "",
"decimals": 2
},
"products": [...],
"categories": [...]
}Response Fields
Top-Level Fields
| Field | Type | Description |
|---|---|---|
baseUrl | string | Prefix for image URLs. Prepend to thumbnail/image paths |
currency | object | Currency information for the market |
products | array | List of available products |
categories | array | List of product categories |
Currency Object
| Field | Type | Description |
|---|---|---|
code | string | Currency code (e.g., USD, EUR) |
left | string | String to prepend to price values (e.g., "$") |
right | string | String to append to price values |
decimals | integer | Number of decimal places for currency |
Product Object
Each product in the products array contains:
json
{
"id": 1,
"sku": "PB001",
"name": "Premium Photo Book",
"description": "A beautiful hardcover photobook",
"descriptionJson": [...],
"metaTitle": "Premium Book",
"thumbnail": "products/pb001-thumb.jpg",
"payment": {
"prices": [
{
"price": 29.99,
"extraCostPerPage": 0.50
}
]
},
"attributes": [...],
"specifications": {...},
"renderOptions": {
"productId": "PB001",
"psp": "PrinterName"
},
"disabled": false
}Key Product Fields
| Field | Type | Description |
|---|---|---|
id | integer | Internal product ID |
sku | string | Product SKU/model identifier |
name | string | Product display name |
description | string | Single-string description. Use this OR descriptionJson |
descriptionJson | array | Structured description. Use this OR description |
metaTitle | string | Short name, useful when space is limited |
thumbnail | string | Path to thumbnail. Prepend with baseUrl |
payment.prices | array | Pricing information (usually contains 1 object) |
payment.prices[0].price | float | Base price of the product |
payment.prices[0].extraCostPerPage | float | Cost per additional page beyond base pages |
attributes | array | Categories and variations (see below) |
specifications | object | Physical product specifications |
renderOptions | object | Product and printer information for API calls |
disabled | boolean | If true, show product grayed out (upcoming product) |
Product Attributes
The attributes array contains categories and sub-categories.
Important
The first object in attributes is always the parent category. This category also appears in the top-level categories array.
json
{
"attributes": [
{
"categoryId": 1,
"type": "category",
"name": "Travel & Adventure",
"subtitle": "Capture your journeys",
"carousel": [
{
"image": "carousel/travel-1.jpg",
"caption": "Explore the world"
}
],
"thumbnail": "categories/travel-thumb.jpg",
"description": "Perfect for travel memories",
"order": 1,
"tag": "Popular",
"topSeller": true,
"disabled": false
},
{
"type": "size",
"name": "8x8 inches",
"thumbnail": "variations/8x8.jpg",
"order": 1
}
]
}Attribute Fields
| Field | Type | Description |
|---|---|---|
type | string | Shows category for categories, else shows sub-category type name |
name | string | Display name |
subtitle | string | Additional descriptive tag |
carousel | array | (category only) Images for carousel display. Prepend with baseUrl |
thumbnail | string | Thumbnail image path. Prepend with baseUrl |
description | string | Single-string description |
descriptionJson | array | Structured description |
order | integer | Sort order |
tag | string | Optional ribbon tag (e.g., "New", "Popular") |
topSeller | boolean | If true, consider prominent placement in UI |
disabled | boolean | If true, show grayed out |
Specifications Object
Contains physical product details:
json
{
"specifications": {
"min": {
"photos": 20,
"pages": 20
},
"max": {
"photos": 200,
"pages": 100
},
"psp": {
"name": "PrinterName",
"leadTime": {
"value": 5,
"unit": "days"
}
}
}
}Key Specification Fields
| Field | Type | Description |
|---|---|---|
min.photos | integer | Minimum number of photos user can select |
max.photos | integer | Maximum number of photos user can select |
psp.name | string | Printer/manufacturer name |
Categories Array
The top-level categories array contains all categories with their associated products:
json
{
"categories": [
{
"categoryId": 1,
"type": "category",
"name": "Travel & Adventure",
"thumbnail": "categories/travel-thumb.jpg",
"products": [1, 2, 5, 8]
}
]
}The products field contains an array of product IDs that belong to this category.
Example Implementation
javascript
async function getProducts(marketId = 0) {
const response = await fetch('https://{ecomm}.photobook.ai/api/v2/products/list-product.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
env: 'dev',
key: 'your-api-key',
language: 'en',
os: 'web',
marketId: marketId,
printType: 'photobook'
})
});
const data = await response.json();
// Helper to get full image URL
const getImageUrl = (path) => data.baseUrl + path;
// Format price with currency
const formatPrice = (price) => {
return `${data.currency.left}${price.toFixed(data.currency.decimals)}${data.currency.right}`;
};
return {
...data,
getImageUrl,
formatPrice
};
}Suggested Practices
- Cache product data: Products don't change frequently. Consider caching with appropriate TTL
- Use
metaTitle: When space is limited, usemetaTitleinstead ofname - Handle disabled products: Show disabled products grayed out to introduce upcoming items
- Highlight top sellers: Products with
topSeller: trueshould get prominent placement - Display categories: Use the carousel images or thumbnails to create an engaging category browser