Skip to main content

Pattern PXM Open API — Website Integration Guide

Everything web developers and integrators need to connect a website directly to Pattern PXM — pull live product data, assets, and attributes to power product detail pages, galleries, and search.

Written by Caden Lindquist
Updated this week

Overview

Pattern PXM's open API lets you integrate your website directly with your PXM (Product Experience Management) system. You can fetch real-time product data, digital assets, and metadata without manual exports or file transfers — keeping your site always in sync with what's in Pattern PXM.

This guide covers the endpoints most relevant for website integrations: authentication, product data, file/asset retrieval, attribute lookup, and search. It is written for web developers and system integrators and includes working code examples in JavaScript and Python.

Base URL: https://entapi.amplifi.io | API Version: v2.1 | Auth: OAuth2 Client Credentials

⚠️ Not using Shopify? This guide is for custom website integrations. If you're on Shopify, Pattern PXM has a dedicated native integration — contact your account manager for details.

How a typical product page integration works:

  1. Authenticate — Exchange your credentials for a bearer token

  2. Fetch productGET /collection/{id}

  3. Fetch filesGET /collection/{id}/files

  4. Fetch attributesGET /attribute

  5. Render page — Display product data on your website

Key Concepts: Terminology

Pattern PXM uses specific terminology in its API that differs from everyday language. Understanding these two mappings will save you a lot of confusion.

  • Collection = Product — A "collection" is a product record. It holds attributes and linked files.

  • Category = Folder — A "category" is an organizational folder, not a product itself. You query Collections to get product data; Categories are purely organizational.

Term

What it means

attribute

A data field on a product or file — e.g. "Color", "Weight", "Description". Attributes have types (Text, Number, List, Pick List, Boolean, Date).

file

A digital asset (image, PDF, video, etc.) stored in Pattern PXM and optionally associated to one or more products.

image-stack

A group of product images organized for display — useful for rendering hero images and galleries efficiently in a single call.

region

A locale or market segment. Collections and files can be scoped to specific regions (e.g., US, UK, EU).

parent / variant

A parent collection groups variant collections (e.g., a t-shirt in sizes S, M, L). Variants share the parent but have their own attributes.

Authentication

Pattern PXM uses OAuth 2.0 Client Credentials — the standard machine-to-machine auth flow. You exchange your client_id and client_secret for a bearer token, then include that token in every subsequent API call.

⚠️ Keep your credentials server-side. Never expose your client_id or client_secret in browser JavaScript, mobile apps, or public repositories. All Pattern PXM API calls should be made from your backend server, which then passes safe data to your frontend.

POST /v2.1/oauth/authorize

When to use: Call this once when your server starts, or when your token expires. Cache the returned token and reuse it — tokens are valid for approximately one year. Do not re-authenticate on every request.

Send a POST with your credentials as a Base64-encoded Basic Auth header and a JSON body specifying the grant type.

POST https://entapi.amplifi.io/v2.1/oauth/authorize
Authorization: Basic Base64(client_id:client_secret)
Content-Type: application/json{
  "grant_type": "client_credentials"
}

JavaScript example:

const clientId     = process.env.AMPLIFI_CLIENT_ID;
const clientSecret = process.env.AMPLIFI_CLIENT_SECRET;
const credentials  = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');const response = await fetch('https://entapi.amplifi.io/v2.1/oauth/authorize', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ grant_type: 'client_credentials' }),
});const { access_token } = await response.json();
// Reuse this token — store it in memory or a short-lived cache
// Authorization header for all subsequent calls:
// 'Authorization': `Bearer ${access_token}`

Python example:

import os, base64, requestsclient_id     = os.environ['AMPLIFI_CLIENT_ID']
client_secret = os.environ['AMPLIFI_CLIENT_SECRET']
credentials   = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()response = requests.post(
    'https://entapi.amplifi.io/v2.1/oauth/authorize',
    headers={
        'Authorization': f'Basic {credentials}',
        'Content-Type': 'application/json',
    },
    json={'grant_type': 'client_credentials'}
)access_token = response.json()['access_token']
HEADERS = {'Authorization': f'Bearer {access_token}'}
# Reuse HEADERS in all subsequent requests

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": "31536000",
  "user": {
    "email": "api-user@yourcompany.com",
    "hostname": "yourcompany.pxm.pattern.com"
  }
}

GET /collection — List Products

Returns a paginated list of product collections. Use this to power catalog pages, product listings, and navigation menus.

Best for: Category/browse pages, sitemaps, bulk syncs of your product catalog, or building a search index. Use limit and offset to paginate through large catalogs. Filter by parent_id to fetch products within a specific category folder.

Query Parameters

Parameter

Type

Description

limit (optional)

integer

Number of records to return. Use for pagination.

offset (optional)

integer

Number of records to skip. Combine with limit to page through results.

parent_id (optional)

string

Return only collections inside this category folder (by category ID).

ids (optional)

array

Comma-separated list of specific collection IDs to fetch in bulk.

region_ids (optional)

array

Filter to collections available in specific regions/locales.

updated_start_date (optional)

date

Only return collections updated after this date (YYYY-MM-DD). Great for incremental syncs.

updated_end_date (optional)

date

Only return collections updated before this date.

minified (optional)

boolean

Return a lighter response (less attribute data). Good for list views where you don't need full detail.

metaonly (optional)

boolean

Return only IDs and names — no attributes. Fastest response, ideal for building navigation.

folder_level (optional)

string

direct = immediate children only. leaf = deepest-level products only (no parent products).

JavaScript — Paginated catalog fetch:

// Fetch all products in a category, 50 at a time
async function fetchAllProductsInCategory(categoryId, token) {
  const products = [];
  let offset = 0;
  const limit = 50;  while (true) {
    const url = new URL('https://entapi.amplifi.io/v2.1/collection');
    url.searchParams.set('parent_id', categoryId);
    url.searchParams.set('limit', limit);
    url.searchParams.set('offset', offset);    const res = await fetch(url, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    const data = await res.json();    if (!data.length) break;   // No more results
    products.push(...data);
    offset += limit;
  }  return products;
}

GET /collection/{id} — Get a Single Product

Returns the full data for a single product (collection) by its unique ID — including all attributes like title, description, specs, pricing, and more.

Best for: Product detail pages (PDPs). When a user lands on a product page, call this endpoint with the product's collection ID to get the full spec sheet. Also useful for populating comparison tables.

Path Parameters

Parameter

Type

Description

id (required)

string (UUID)

The unique ID of the collection/product.

Example Response:

{
  "id": "a1b2c3d4-1234-5678-abcd-ef1234567890",
  "name": "Heavy Duty 5/8\" Garden Hose - 50ft",
  "additional_title": "Model HG-5058",
  "parent_id": "cat-uuid-garden-category",
  "collection_type": "variant",
  "published": true,
  "attributes": [
    { "id": "attr-uuid-001", "label": "Color",    "value": "Green", "value_type": "Text" },
    { "id": "attr-uuid-002", "label": "Length",   "value": "50ft",  "value_type": "Text" },
    { "id": "attr-uuid-004", "label": "Max PSI",  "value": 150,     "value_type": "Number" },
    { "id": "attr-uuid-005", "label": "In Stock", "value": true,    "value_type": "Boolean" }
  ],
  "created_date": "2024-01-15T10:23:00Z",
  "update_date": "2024-11-02T08:45:00Z"
}

💡 Working with attributes: Attributes are returned as an array. Iterate over them and map by label (the human-readable name) to display on your page. The value_type field tells you how to render the value — use a checkbox for Boolean, a formatted number for Number, or plain text for Text.

JavaScript — Fetch and render a product:

async function getProduct(collectionId, token) {
  const res = await fetch(
    `https://entapi.amplifi.io/v2.1/collection/${collectionId}`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );
  const product = await res.json();  // Convert attributes array to a convenient key-value map
  const attrs = Object.fromEntries(
    product.attributes.map(a => [a.label, a.value])
  );  return {
    id:          product.id,
    name:        product.name,
    description: attrs['Description'] ?? '',
    color:       attrs['Color'] ?? '',
    inStock:     attrs['In Stock'] ?? false,
  };
}

GET /collection/{id}/files — Get Product Assets

Returns all files (images, PDFs, videos, documents) associated with a specific product. Use this to power product image galleries, downloadable spec sheets, and media libraries.

Best for: Loading all assets for a product detail page. Each file includes CDN URLs at multiple sizes so you can choose the right resolution for every context (thumbnail, gallery, full-size). For pure image gallery use, also consider /collection/{id}/image-stacks for more structured image presentation.

File Variant Sizes

Variant Key

Typical Use

variants.thumb

Thumbnails, product cards in listing pages

variants.small

Compact product images, mobile views

variants.medium

Standard product images, gallery grid

variants.large

Full-width hero images, lightbox views

variants.preview

High-quality preview (between medium and large)

JavaScript — Build a product image gallery:

async function getProductImages(collectionId, token) {
  const res = await fetch(
    `https://entapi.amplifi.io/v2.1/collection/${collectionId}/files`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );
  const files = await res.json();  const images    = files.filter(f => f.metadata?.mime_type?.startsWith('image/'));
  const documents = files.filter(f => f.metadata?.mime_type === 'application/pdf');  return {
    gallery: images.map(img => ({
      id:       img.id,
      thumb:    img.variants?.thumb,
      medium:   img.variants?.medium,
      full:     img.variants?.large,
      altText:  img.metadata?.caption ?? img.metadata?.file_name,
    })),
    downloads: documents.map(doc => ({
      id:   doc.id,
      name: doc.metadata?.file_name,
      url:  doc.variants?.preview ?? doc.metadata?.cdn_url,
    })),
  };
}

GET /collection/{id}/image-stacks — Get Structured Product Images

Returns product images organized into named stacks — pre-grouped sets of images (e.g., "Front View", "Lifestyle", "Detail Shots"). This is the most efficient way to populate a product image gallery when images have been organized in Pattern PXM.

Best for: Product detail page image galleries where images are organized into named groups. Lets you request a specific image size and format in one call. Ideal when you need images in a specific format (e.g., WebP for performance) or a specific size tier.

Query Parameters

Parameter

Type

Description

size (optional)

string

One of: original, thumbnail, small, medium, large.

file_type (optional)

string

One of: jpg, png, webp. Use webp for best web performance.

stack_ids (optional)

array

Comma-separated list of specific stack IDs to fetch.

JavaScript — Fetch WebP gallery images:

async function getProductGallery(collectionId, token) {
  const url = new URL(
    `https://entapi.amplifi.io/v2.1/collection/${collectionId}/image-stacks`
  );
  url.searchParams.set('size', 'medium');
  url.searchParams.set('file_type', 'webp');  const res    = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  const stacks = await res.json();  return stacks.map(stack => ({
    name:   stack.name,
    images: stack.files ?? [],
  }));
}

💡 Performance tip: Request file_type=webp and the appropriate size for your layout. Serving WebP at the correct size is one of the biggest wins for page load speed on image-heavy product pages.

GET /file — List Files

Returns a list of files, optionally filtered by collection IDs, date ranges, or region. Use this when you need to query assets across multiple products at once.

Best for: Bulk asset operations — syncing a media library, generating a sitemap of all assets, or fetching all files updated since a given date for an incremental sync. For files associated with a specific product, prefer GET /collection/{id}/files instead.

Query Parameters

Parameter

Type

Description

collection_ids (optional)

array

Comma-separated list of collection IDs — returns files linked to any of those products.

region_ids (optional)

array

Filter to files available in specific regions.

limit (optional)

integer

Number of files to return per page.

offset (optional)

integer

Pagination offset.

updated_start_date (optional)

date

Only return files updated after this date. Ideal for delta syncs.

minified (optional)

boolean

Return lighter responses (omits some metadata).

JavaScript — Incremental sync since last run:

async function getUpdatedFiles(lastSyncDate, token) {
  const url = new URL('https://entapi.amplifi.io/v2.1/file');
  url.searchParams.set('updated_start_date', lastSyncDate); // "2025-01-01"
  url.searchParams.set('limit', 100);  const res = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  return res.json();
}

GET /file/{id} — Get a Single File

Returns the full metadata and CDN URLs for a single file by its unique ID.

Best for: When you already have a file ID (e.g., from a collection's file list or a search result) and need the full details: CDN URLs at all sizes, metadata, dimensions, file type, and any attributes attached to that asset.

Example Response:

{
  "id": "f1a2b3c4-0000-1111-aaaa-bbbbccccdddd",
  "metadata": {
    "file_name": "garden-hose-50ft-hero.jpg",
    "caption":   "Green 50ft garden hose coiled on white background",
    "mime_type": "image/jpeg"
  },
  "file_dimension": "3000px x 3000px",
  "file_size": 2048576,
  "variants": {
    "thumb":   "https://cdn.amplifi.io/.../thumb/garden-hose-50ft-hero.jpg",
    "small":   "https://cdn.amplifi.io/.../small/garden-hose-50ft-hero.jpg",
    "medium":  "https://cdn.amplifi.io/.../medium/garden-hose-50ft-hero.jpg",
    "large":   "https://cdn.amplifi.io/.../large/garden-hose-50ft-hero.jpg"
  },
  "auto_label": ["garden", "hose", "outdoor", "green"]
}

ℹ️ Alt text tip: The metadata.caption field is a great source for image alt text. The auto_label array contains AI-generated tags from Google Vision that can supplement your SEO metadata.

GET /attribute — Get Attribute Definitions

Returns the global attribute schema — all attribute definitions configured in your Pattern PXM account. Use this to understand the structure of your product data before displaying it.

Best for: Bootstrapping your integration. Fetch the attribute list once (or cache it) to build a map of attribute IDs to human-readable labels and types. Also useful for building faceted search filters (e.g., filter by Color, Size, Material).

Attribute Value Types

value_type

How to render

Example

Text

Plain string

"Forest Green"

Number

Numeric, apply units from label

150

Boolean

Yes/No, checkbox, badge

true

Date

Format with locale date library

"2025-06-01"

List

Comma-separated or multi-value

"Red, Green, Blue"

Pick List

Single value from predefined options

"Large"

JavaScript — Build an attribute lookup map:

// Fetch once and cache — attribute definitions rarely change
async function buildAttributeMap(token) {
  const res   = await fetch('https://entapi.amplifi.io/v2.1/attribute', {
    headers: { 'Authorization': `Bearer ${token}` }
  });
  const attrs = await res.json();  return Object.fromEntries(
    attrs.map(a => [a.id, { label: a.label, type: a.value_type }])
  );
}function renderAttributeValue(value, type) {
  switch (type) {
    case 'Boolean': return value ? 'Yes' : 'No';
    case 'Number':  return Number(value).toLocaleString();
    case 'Date':    return new Date(value).toLocaleDateString();
    default:        return String(value ?? '');
  }
}

GET /file/search/{filename} — Search Files by Name

Search for a file by its exact or partial filename. Returns matching file records including all metadata and CDN URLs.

Best for: Looking up a specific asset when you know its filename but not its Pattern PXM file ID. Useful for migration scripts, filename-based DAM workflows, or when your existing system references assets by filename rather than ID.

⚠️ URL-encode filenames. Filenames with spaces, ampersands, or special characters must be URL-encoded before including them in the path. Use encodeURIComponent() in JavaScript or urllib.parse.quote() in Python.

async function searchFileByName(filename, token) {
  const encoded = encodeURIComponent(filename);
  const res = await fetch(
    `https://entapi.amplifi.io/v2.1/file/search/${encoded}`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );
  return res.json();
}

GET /v2/{entity}/search — Keyword Search

Full-text keyword search across either products (collections, referred to as "folders" in this endpoint) or files. Use this to power your site's search bar.

Best for: Site search functionality — when users type a query into your search box and you need to return matching products or assets. The folder entity searches product collections; the file entity searches digital assets.

📝 Terminology note: This endpoint uses folder to refer to what Pattern PXM calls a "collection" (a product). This is the only endpoint where this naming occurs. A v3 endpoint is also available at /v3/{entity}/search — it returns the same results but includes a total count in the response, useful for building paginated search UIs.

Query Parameters

Parameter

Type

Description

entity (required)

string

Either folder (search products/collections) or file (search assets).

keyword (required)

string

The search term. Searches across product names and attribute values.

from (optional)

integer

Pagination offset. Default: 0. Max: 10,000.

size (optional)

integer

Number of results to return. Default: 100. Max: 1,000.

JavaScript — v2 search:

async function searchProducts(keyword, token, page = 0, pageSize = 20) {
  const url = new URL('https://entapi.amplifi.io/v2/folder/search');
  url.searchParams.set('keyword', keyword);
  url.searchParams.set('from', page * pageSize);
  url.searchParams.set('size', pageSize);  const res  = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  const hits = await res.json();
  return hits;
}

JavaScript — v3 search (with total count for paginated UIs):

async function searchProductsV3(keyword, token, page = 0, pageSize = 20) {
  const url = new URL('https://entapi.amplifi.io/v3/folder/search');
  url.searchParams.set('keyword', keyword);
  url.searchParams.set('from', page * pageSize);
  url.searchParams.set('size', pageSize);  const res            = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  const { hits, total } = await res.json();  return {
    results:     hits,
    total:       total,
    totalPages:  Math.ceil(total / pageSize),
    currentPage: page,
  };
}

Best Practices & Rate Limits

  • 🔐 Keep auth server-side — Never expose your client_id or client_secret in frontend code. All Pattern PXM API calls should originate from your backend.

  • ♻️ Cache your token — Tokens last approximately one year. Store the token in memory and only re-authenticate when you receive a 401 response.

  • 📄 Paginate large requests — Always use limit and offset when fetching collections or files. Don't attempt to fetch all records in a single request.

  • Cache attribute definitions — Fetch GET /attribute once at startup and cache the result. Attribute schemas change infrequently — daily re-fetching is sufficient.

  • 🖼️ Use the right image size — Use thumb for listing pages, medium for gallery grids, and large for lightboxes. Request webp format for best performance.

  • 🔄 Use incremental syncs — For background sync jobs, use updated_start_date on /collection and /file to fetch only what changed since your last sync run.

  • 🌐 Use v3 search for pagination UI — Use GET /v3/{entity}/search when you need a total result count to build "Page X of Y" pagination.

  • 🗺️ URL-encode search terms — Always pass search keywords and filenames through encodeURIComponent() before including them in URLs.

  • ⏱️ Respect the rate limit — The API allows up to 1,000 requests per 60 seconds. If you exceed this, you'll receive a 429 response with a Retry-After header. Build in retry logic.

  • 🔗 Use CDN URLs for asset delivery — All file variants are hosted on Amplifi's CDN. These URLs are permanent, publicly accessible, and globally fast — link to them directly from your website.

  • 👤 Use a dedicated API user — Create a single dedicated API user (e.g., api@yourcompany.com) in your Pattern PXM instance for all API requests.

ℹ️ API URL stability: The Amplifi API base URL (https://entapi.amplifi.io) is not affected by the platform's URL migration from amplifi.io to pxm.pattern.com. Your integration does not need to change if your customers update their instance URLs.

Error Codes

Code

Meaning

Common Cause & Fix

400

Bad Request

Invalid query parameter or malformed JSON. Check parameter names and types against the docs above.

401

Unauthorized

Your token is missing, expired, or malformed. Re-authenticate by calling POST /oauth/authorize to get a fresh token.

404

Not Found

The ID in the path doesn't exist (or you don't have access to it). Verify the collection or file ID is correct.

429

Too Many Requests

You've exceeded 1,000 requests per 60 seconds. Check the Retry-After header and wait that many seconds before retrying.

500

Internal Server Error

Unexpected server-side error. Retry with exponential backoff. If it persists, contact Pattern PXM support.

Recommended retry logic

async function apiFetch(url, token, refreshToken) {
  let res = await fetch(url, {
    headers: { 'Authorization': `Bearer ${token}` }
  });  // Handle rate limiting — respect the Retry-After header
  if (res.status === 429) {
    const retryAfter = parseInt(res.headers.get('Retry-After') ?? '60', 10);
    await new Promise(r => setTimeout(r, retryAfter * 1000));
    res = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  }  // Re-authenticate on 401 and retry once
  if (res.status === 401) {
    const newToken = await refreshToken();
    res = await fetch(url, { headers: { 'Authorization': `Bearer ${newToken}` } });
  }  // Retry 500s with simple backoff
  if (res.status === 500) {
    await new Promise(r => setTimeout(r, 1000));
    res = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } });
  }  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(`API error ${res.status}: ${err.message ?? 'Unknown error'}`);
  }  return res.json();
}

Quick Start — Full Product Page Example

Here's a complete minimal example that authenticates, fetches a product, and retrieves its images — the core of any product detail page integration.

import { Buffer } from 'buffer'; // Node.js — not needed in browsersconst BASE_URL = 'https://entapi.amplifi.io';// 1. Authenticate
async function authenticate() {
  const creds = Buffer.from(
    `${process.env.AMPLIFI_CLIENT_ID}:${process.env.AMPLIFI_CLIENT_SECRET}`
  ).toString('base64');  const res = await fetch(`${BASE_URL}/v2.1/oauth/authorize`, {
    method: 'POST',
    headers: { 'Authorization': `Basic ${creds}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ grant_type: 'client_credentials' }),
  });  const { access_token } = await res.json();
  return access_token;
}// 2. Fetch product + images
async function getProductPageData(collectionId, token) {
  const headers = { 'Authorization': `Bearer ${token}` };  // Fetch product details and images in parallel
  const [product, images] = await Promise.all([
    fetch(`${BASE_URL}/v2.1/collection/${collectionId}`, { headers }).then(r => r.json()),
    fetch(`${BASE_URL}/v2.1/collection/${collectionId}/image-stacks?size=medium&file_type=webp`, { headers }).then(r => r.json()),
  ]);  const attrs = Object.fromEntries(
    product.attributes.map(a => [a.label, a.value])
  );  return {
    id:          product.id,
    name:        product.name,
    description: attrs['Description'] ?? '',
    specs:       product.attributes,
    gallery:     images.flatMap(stack => stack.files ?? []),
  };
}// 3. Use it
const token    = await authenticate();
const pageData = await getProductPageData('YOUR-COLLECTION-ID-HERE', token);console.log(pageData.name);       // "Heavy Duty 5/8\" Garden Hose - 50ft"
console.log(pageData.gallery[0]); // First gallery image with CDN URL

Need help? Contact your Amplifi account team or reach out via the support portal at support.amplifi.io. Your client_id and client_secret are provided by your account manager — if you don't have them yet, request them before beginning your integration.

Did this answer your question?