Інтеграція Public API Alter Product

Public API призначений для міжсерверних інтеграцій із магазинами, комерційними серверними системами, плагінами WordPress/WooCommerce та зовнішніми виробничими процесами.

Автентифікація та базова URL-адреса

https://alterproduct.com/public-api/v1

Створіть облікові дані API на панелі налаштувань електронної комерції. Access Token показується лише раз, тому одразу збережіть його в серверному сховищі секретів.

Зберігайте Access Key і Access Token на сервері. Кінцеві точки з автентифікацією відхиляють браузерні виклики із заголовками Origin або Referer.

Права облікових даних можна обмежувати. Використовуйте GET /auth/check, щоб перевірити активний магазин, можливості тарифу та права, повернені для цих облікових даних.

x-alter-access-key: YOUR_API_KEY
x-alter-access-token: YOUR_API_TOKEN
ПараметрОбов’язковоПодробиці
x-alter-access-keyтакПублічний ідентифікатор облікових даних.
x-alter-access-tokenтакСекретний токен у парі з ключем доступу.
x-alter-client-fingerprintніНеобов’язковий стабільний відбиток для обмеження частоти сеансів вбудовування.
Authorizationлише середовище виконанняТокен Bearer, повернений POST /embed/session, для використання в /runtime/bootstrap.

Перевірка підключення

Використайте кінцеву точку перевірки автентифікації, перш ніж увімкнути синхронізацію чи вбудовування в робочій інтеграції.

GET https://alterproduct.com/public-api/v1/auth/check

Приклад запиту (fetch)

const response = await fetch('https://alterproduct.com/public-api/v1/auth/check', {
  method: 'GET',
  headers: {
    'x-alter-access-key': process.env.ALTER_ACCESS_KEY,
    'x-alter-access-token': process.env.ALTER_ACCESS_TOKEN
  }
});

const payload = await response.json();

if (!response.ok) {
  throw new Error(payload?.code || payload?.error || `Alter API ${response.status}`);
}

console.log(payload);

Приклад відповіді

{
  "ok": true,
  "message": "success",
  "storefrontId": 12,
  "userOwnerId": 34,
  "credentialId": 56,
  "scopes": ["orders:read", "orders:write", "products:read"],
  "plan": {
    "requiredPlan": "Business",
    "currentPlanName": "Business",
    "eligible": true,
    "runtimeFlags": {
      "viewer": true,
      "configurator": true,
      "customizer": true
    },
    "limits": {
      "activeRuntimeBindingsLimit": 100,
      "monthlyReassignmentLimit": 1000,
      "monthlyEmbedTokenLimit": 50000
    }
  }
}

Наведена нижче допоміжна функція використовується в інших прикладах. Це звичайний fetch, який може працювати в Node.js 18+ або будь-якому серверному середовищі з підтримкою fetch.

const ALTER_API_BASE = 'https://alterproduct.com/public-api/v1';

const authHeaders = {
  'x-alter-access-key': process.env.ALTER_ACCESS_KEY,
  'x-alter-access-token': process.env.ALTER_ACCESS_TOKEN
};

async function alterFetch(path, options = {}) {
  const response = await fetch(`${ALTER_API_BASE}${path}`, {
    ...options,
    headers: {
      ...authHeaders,
      ...(options.body ? { 'Content-Type': 'application/json' } : {}),
      ...options.headers
    }
  });

  const payload = await response.json().catch(() => null);

  if (!response.ok) {
    throw new Error(payload?.code || payload?.error || `Alter API ${response.status}`);
  }

  return payload;
}

Огляд кінцевих точок

Таблиця нижче відповідає публічним маршрутам, підключеним у backend-public-api/app.js. Шляхи наведено з префіксом публічного проксі для зовнішніх інтеграцій.

МетодКінцева точкаОписДоступ
GET/public-api/healthzПеревірка стану сервісу.публічний
GET/public-api/v1/auth/checkПеревіряє облікові дані й повертає магазин, права доступу та можливості тарифу.будь-які автентифіковані облікові дані
GET/public-api/v1/customer-ordersПовертає список замовлень покупців із пагінацією та фільтрами.orders:read
GET/public-api/v1/customer-orders/:idПовертає одне замовлення покупця з налаштованими товарними позиціями.orders:read
POST/public-api/v1/customer-orders/batchПовертає до 100 замовлень за ID.orders:read
PATCH/public-api/v1/customer-orders/:id/statusОновлює стан замовлення.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantityОновлює кількість вибраних позицій замовлення.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantity/allУстановлює однакову кількість для кожної позиції замовлення.orders:write
DELETE/public-api/v1/customer-orders/:idВидаляє замовлення покупця, що належить власнику магазину.orders:write
GET/public-api/v1/productsПовертає товари/дизайни магазину з доступністю вбудовування та URL-адресами медіа.products:read
GET/public-api/v1/products/:idПовертає один товар/дизайн магазину.products:read
POST/public-api/v1/embed/sessionВидає короткостроковий JWT для вбудованих інструментів, зокрема генератора моделей.embed:session:create
GET/public-api/v1/runtime/bootstrapВизначає контекст середовища виконання за JWT вбудовування.токен вбудовування Bearer
GET/public-api/v1/assetsПовертає список ресурсів каталогу запитаного типу.будь-які автентифіковані облікові дані
GET/public-api/v1/assets/:type/:assetIdПовертає маніфест ресурсу з ролями доступних для завантаження файлів.будь-які автентифіковані облікові дані
GET/public-api/v1/assets/:type/:assetId/files/:roleЗавантажує файл ресурсу за роллю.будь-які автентифіковані облікові дані
GET/public-api/v1/design-importsПовертає список доступних для імпорту дизайнів, розміщених в Alter.автентифіковані облікові дані, потрібен тариф Business
GET/public-api/v1/design-imports/:idПовертає дані імпорту дизайну й описи файлів.автентифіковані облікові дані, потрібен тариф Business
GET/public-api/v1/design-imports/:id/files/:fileIdЗавантажує файл з опису імпорту дизайну.автентифіковані облікові дані, потрібен тариф Business
GET/public-api/v1/file/public/products/:productId/:sizeПовертає публічний перегляд товару. Розмір має бути small.png, medium.png або big.png.публічний
GET/public-api/v1/file/protected/:keyПовертає захищений файл за ключем сховища.підписана URL-адреса або files:read
GET/public-api/v1/fontsПовертає всі доступні шрифти.публічний
GET/public-api/v1/currenciesПовертає всі валюти.публічний
POST/public-api/v1/runtime-bindings/sync-from-wordpressСтворює або оновлює прив’язки середовища виконання зі зіставлень товарів WordPress.будь-які автентифіковані облікові дані
PATCH/public-api/v1/runtime-bindings/:idЧастково оновлює прив’язку середовища виконання.будь-які автентифіковані облікові дані
POST/public-api/v1/runtime-bindings/:id/activateАктивує прив’язку середовища виконання.будь-які автентифіковані облікові дані
POST/public-api/v1/runtime-bindings/:id/deactivateДеактивує прив’язку середовища виконання.будь-які автентифіковані облікові дані
POST/public-api/v1/wp-connect/exchangeОбмінює код автоматичного підключення WordPress на облікові дані API.одноразовий код передачі
GET/public-api/v1/model-generator/catalogВиводить видимі товари генератора, конфігурації та ревізії шаблонів.embed:session:create
GET/public-api/v1/model-generator/modelsВиводить моделі з дескрипторами, що фіксують вихідні ревізії генератора для імпорту.embed:session:create
GET/public-api/v1/model-generator/designer-catalogПовертає каталог моделей генератора, який використовує Designer.embed:session:create
GET/public-api/v1/model-generator/projectsВиводить проєкти генератора власника й глобально доступні проєкти.embed:session:create
GET/public-api/v1/model-generator/projects/:projectIdПовертає найновішу або вибрану ревізію проєкту, шаблон і маніфест файлів.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/revisions/:revisionПовертає найновішу або вибрану ревізію проєкту, шаблон і маніфест файлів.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/artifacts/:artifactIdЗавантажує артефакт після перевірки доступу до його проєкту.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/templateПовертає доступний документ шаблону для вибраної ревізії конфігурації.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/importПовертає пакет імпорту шаблону з файлами залежностей.embed:session:create
GET/public-api/v1/model-generator/mannequinsПовертає обидва манекени та дескриптори їхніх ресурсів.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assetsВиводить ресурси бібліотеки текстур або фонів із файлами для імпорту.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assets/:assetIdПовертає один ресурс текстури або фону з файлами для імпорту.embed:session:create
GET/public-api/v1/model-generator/public-files/:keyЗавантажує дозволений файл залежності генератора.embed:session:create

Замовлення покупців

Кінцеві точки замовлень дозволяють зовнішньому магазину читати налаштовані позиції, змінювати кількість, переводити замовлення між станами виконання та видаляти покинуті замовлення.

ПараметрОбов’язковоПодробиці
nameніШукає за назвою дизайну та числовим ID замовлення.
category_idніФільтрує за ID категорії товару.
order_statusніОдин із дозволених станів замовлення.
offsetніТипово 0. Має бути >= 0.
limitніТипово 9 для цього контролера, максимум 50.
order_byніid, created_at або design_name.
directionніASC або DESC.

Приклад запиту (fetch)

const params = new URLSearchParams({
  limit: '20',
  offset: '0',
  order_status: 'shopping_cart',
  order_by: 'created_at',
  direction: 'DESC'
});

const orders = await alterFetch(`/customer-orders?${params.toString()}`);

const order = await alterFetch('/customer-orders/123');

const batch = await alterFetch('/customer-orders/batch', {
  method: 'POST',
  body: JSON.stringify({
    customerOrderIds: [123, 124, 125]
  })
});

Дозволені значення

СтанОпис
shopping_cartЗамовлення в кошику; покупець ще може редагувати конфігурацію.
editableПокупець усе ще може редагувати замовлення.
paidЗамовлення оплачене й готове до виконання.
processingЗамовлення виконується.
completedЗамовлення виконане.
cancelledЗамовлення скасоване.

Приклад запиту (fetch)

await alterFetch('/customer-orders/123/status', {
  method: 'PATCH',
  body: JSON.stringify({
    status: 'processing'
  })
});

await alterFetch('/customer-orders/123/quantity', {
  method: 'PATCH',
  body: JSON.stringify({
    items: [
      { orderDetailId: 987, quantity: 3 }
    ]
  })
});

await alterFetch('/customer-orders/123/quantity/all', {
  method: 'PATCH',
  body: JSON.stringify({
    quantity: 2
  })
});

await alterFetch('/customer-orders/123', {
  method: 'DELETE'
});

Приклад відповіді

{
  "order": {
    "id": 123,
    "customizerId": 381,
    "orderStatus": "shopping_cart",
    "createdAt": "2026-05-28T10:15:00.000Z",
    "customizerOrderURL": "https://alterproduct.com/app/customizer/381/123",
    "productItems": [
      {
        "id": 987,
        "model3d": { "id": 381 },
        "size": {
          "id": 395,
          "name": { "pl": "M", "en": "M" },
          "measureSize": null
        },
        "material": {
          "id": 2,
          "name": { "pl": "Bawełna", "en": "Cotton" }
        },
        "printType": {
          "id": 1,
          "name": { "pl": "DTG", "en": "DTG" }
        },
        "color": {
          "id": 418,
          "name": { "pl": "Domyślny", "en": "Default" },
          "hex": "#ffffff"
        },
        "variant": {
          "id": 531,
          "metadata": null,
          "stockQuantity": 25
        },
        "unitPrice": { "value": 12.5, "currency": "EUR" },
        "totalPrice": { "value": 37.5, "currency": "EUR" },
        "quantity": 3
      }
    ],
    "customizerName": "Men's T-Shirt",
    "productGroup": {
      "id": 4,
      "name": { "pl": "Koszulka", "en": "T-Shirt" }
    },
    "totalPrice": { "value": 37.5, "currency": "EUR" }
  }
}

Товари магазину

Кінцеві точки товарів повертають дизайни магазину, які можна вбудувати як Viewer, Configurator або Customizer.

ПараметрОбов’язковоПодробиці
nameніШукає за назвою товару/дизайну.
customizerніtrue або false.
offsetніТипово 0. Має бути >= 0.
limitніТипово 9, максимум 50.
order_byніid, name або created_at.
directionніASC або DESC.

Приклад запиту (fetch)

const params = new URLSearchParams({
  limit: '20',
  offset: '0',
  name: 't-shirt',
  customizer: 'true',
  order_by: 'created_at',
  direction: 'DESC'
});

const products = await alterFetch(`/products?${params.toString()}`);
const product = await alterFetch('/products/381');

Приклад відповіді

{
  "products": {
    "items": [
      {
        "id": 381,
        "name": "Men's T-Shirt",
        "createdAt": "2026-01-03T23:55:05.000Z",
        "productId": 4,
        "media": {
          "img": {
            "big": "https://alterproduct.com/public-api/v1/file/public/products/4/big.png",
            "medium": "https://alterproduct.com/public-api/v1/file/public/products/4/medium.png",
            "small": "https://alterproduct.com/public-api/v1/file/public/products/4/small.png"
          },
          "mockups": []
        },
        "storefrontProduct": {
          "id": 89,
          "idUserDesign": 381,
          "shareAccess": "public",
          "isCustomizer": 1
        },
        "runtimeBindings": [
          {
            "id": 42,
            "runtimeType": "customizer",
            "status": "active",
            "externalProductId": "wc_123"
          }
        ],
        "embeddable": {
          "viewer": true,
          "configurator": true,
          "customizer": true
        }
      }
    ],
    "total": 1
  }
}

Сеанси вбудовування та початкове завантаження середовища виконання

Створіть короткостроковий токен вбудовування на сервері, передайте його iframe/середовищу виконання, а потім дозвольте середовищу викликати bootstrap із токеном Bearer.

ПараметрОбов’язковоПодробиці
runtimeBindingIdрекомендованоБажаний ідентифікатор активних прив’язок середовища виконання.
toolобов’язково без runtimeBindingIddesigner | viewer | configurator | customizer | model-generator
toolIdtool: model-generatorДодатний числовий ID локального проєкту генератора, а не його UUID або ID товару WooCommerce.
originтакOrigin, де відображається вбудований інструмент, наприклад https://yourstore.com.
designIdодин ідентифікаторID дизайну Alter Product. Не поєднуйте з orderId.
orderIdодин ідентифікаторID замовлення Customizer. Дійсний лише для customizer.
cartKey + cartModeніКонтекст кошика лише для Customizer. cartMode має значення view або edit.

Приклад запиту (fetch)

const session = await alterFetch('/embed/session', {
  method: 'POST',
  headers: {
    'x-alter-client-fingerprint': '9f1b7a5e4b3c2d1f9f1b7a5e4b3c2d1f'
  },
  body: JSON.stringify({
    runtimeBindingId: 42,
    origin: 'https://yourstore.com'
  })
});

const bootstrapResponse = await fetch('https://alterproduct.com/public-api/v1/runtime/bootstrap', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${session.token}`
  }
});

const bootstrap = await bootstrapResponse.json();
console.log({ session, bootstrap });

Примітки

await alterFetch('/embed/session', {
  method: 'POST',
  body: JSON.stringify({
    tool: 'customizer',
    origin: 'https://yourstore.com',
    orderId: 123
  })
});

await alterFetch('/embed/session', {
  method: 'POST',
  body: JSON.stringify({
    tool: 'viewer',
    origin: 'https://yourstore.com',
    designId: 381
  })
});

Приклад відповіді

{
  "token": "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEifQ...",
  "expiresIn": 900,
  "kid": "1",
  "mode": "design",
  "runtimeBindingId": 42,
  "runtimeType": "customizer"
}

Runtime bootstrap

{
  "runtimeBindingId": 42,
  "designId": 381,
  "productId": "wc_123",
  "runtimeType": "customizer",
  "storageMode": "wordpress_local",
  "manifestUrl": "https://yourstore.com/wp-content/uploads/alter/381/manifest.json",
  "assetBaseUrl": "https://yourstore.com/wp-content/uploads/alter/381/",
  "manifestHash": "a3b1...",
  "planCapabilities": {
    "viewer": true,
    "configurator": true,
    "customizer": true
  },
  "cartKey": null,
  "cartMode": null,
  "orderId": null
}

Генератор 3D-моделей

Ендпоїнти імпорту генератора підтримують лише читання під час обміну між серверами. Вони потребують стандартних заголовків API, дозволу embed:session:create й активного тарифу. Авторизація імпорту не створює сеанс редактора й не витрачає його місячний ліміт. Відкриття редактора використовує той самий лічильник monthlyEmbedTokenLimit, що й решта вбудованих інструментів.

Пошук та імпорт моделей із генератором

Використовуйте /model-generator/models, щоб отримати перелік доступних моделей із генераторами. Дескриптор generator фіксує projectId, revision, configurationId, templateRevision, productId і productModel3dId. Перейдіть за його importPath, щоб отримати саме цю вихідну ревізію. Маніфести ресурсів товару також надають generators і дескриптор generator для кожної моделі. Шаблони можна імпортувати окремо за конфігурацією та ревізією.

Фільтри каталогів

Кінцева точкаПодробиці
/model-generator/modelsПерелік моделей: name (або q), categoryId, scope (all, own, global), limit (1–50) і offset.
/model-generator/catalogКаталог шаблонів: generatorType, productId, audience, q, templateKey, configurationId, limit і offset.
/model-generator/projectsПерелік проєктів: configurationId, q, scope (all, own, global), limit і offset. Публічний проксі за замовчуванням використовує scope all.
/model-generator/image-libraries/:kind/assetsБібліотеки текстур і фонів: kind має значення texture або background; q, category і mapType фільтрують доступні ресурси.

Імпорт проєкту містить document, revision, template і маніфест files. Кожен файл надає path у просторі /v1/model-generator/; під час завантаження з Alter Product додайте перед ним /public-api. Скопіюйте потрібні файли до власного сховища та замініть вихідні посилання локальними. Імпортуйте манекени й бібліотеки текстур через їхні ендпоїнти каталогів; public-files допускає лише дозволені шляхи ресурсів, а шаблони проходять перевірку доступу до конфігурації та ревізії.

Приклад запиту (fetch)

// Server-side: uses the alterFetch helper and authHeaders defined above.
const catalog = await alterFetch('/model-generator/models?' + new URLSearchParams({
  scope: 'all', limit: '24', offset: '0'
}));

const selected = catalog.items[0];
if (!selected?.generator) throw new Error('Select an available generator model');

const importPath = selected.generator.importPath;
if (!importPath.startsWith('/v1/model-generator/projects/')) {
  throw new Error('Invalid generator import path');
}
const bundle = await alterFetch(importPath.slice('/v1'.length));

for (const file of bundle.files) {
  if (!file.path.startsWith('/v1/model-generator/')) {
    throw new Error('Invalid generator file path');
  }
  const response = await fetch('https://alterproduct.com/public-api' + file.path, {
    headers: authHeaders,
    redirect: 'error'
  });
  if (!response.ok) throw new Error(`File download failed: ${response.status}`);
  const bytes = new Uint8Array(await response.arrayBuffer());
  // Persist bytes in your local storage; record the mapping from
  // file.sourceHref / file.href to the resulting local file reference.
}
// Persist bundle.document, bundle.template and revision metadata locally.
// Import the related product asset and its textures/mockups as needed:
const product = await alterFetch('/assets/products/' + selected.generator.productId);
const mannequins = await alterFetch('/model-generator/mannequins');
console.log({ product, mannequins });

Сеанс редактора й локальне зберігання

Створіть сеанс редактора з tool: model-generator, додатним числовим toolId локального проєкту генератора (не його UUID чи ID товару WooCommerce) і дозволеним origin магазину. Не передавайте designId, orderId, runtimeBindingId або поля кошика для цього інструмента. UUID проєкту генератора — окремий ідентифікатор. Передайте отриманий токен через handshake iframe; runtime bootstrap поверне контекст генератора зі storageMode: wordpress_local.

// Server-side, after authorizing the merchant's access to this local project.
const localProjectId = 42; // Local generator project ID, not its UUID or WC product ID.
const session = await alterFetch('/embed/session', {
  method: 'POST',
  body: JSON.stringify({
    tool: 'model-generator',
    toolId: localProjectId,
    origin: 'https://yourstore.com'
  })
});

// The iframe receives session.token through ALTER_CUSTOMIZER_SESSION_READY.
// Do not put API credentials or the token in the iframe URL.
const bootstrapResponse = await fetch('https://alterproduct.com/public-api/v1/runtime/bootstrap', {
  headers: { Authorization: `Bearer ${session.token}` }
});
if (!bootstrapResponse.ok) throw new Error('Generator bootstrap failed');
const context = await bootstrapResponse.json();
console.log(context);

Приклад відповіді

{
  "runtimeBindingId": null,
  "designId": null,
  "productId": 42,
  "toolId": 42,
  "runtimeType": "model-generator",
  "storageMode": "wordpress_local",
  "parentOrigin": "https://yourstore.com"
}
// Host page: WordPress returns a numeric toolId and a UUID in id.
const url = new URL('https://alterproduct.com/app/model-generator');
url.search = new URLSearchParams({
  embedded: '1',
  lng: 'en',
  parentOrigin: window.location.origin,
  toolId: String(localProject.toolId),
  serverProjectId: localProject.id
}).toString();
// Optional: serverProjectRevision pins an existing saved revision.
iframe.src = url.toString();
// Install the authenticated handshake and storage bridge described below.
// Setting iframe.src alone does not authorize the editor or provide storage.

Повідомлення iframe для зв’язку з WordPress

Плагін WordPress забезпечує зв’язок із локальним сховищем і перевіряє права адміністратора або менеджера WooCommerce. Він перевіряє origin iframe, вихідне вікно, nonce, ідентифікатор запиту й дозволені шляхи проєкту. Локальні операції читання та запису спрямовуються до /wp-json/alter-wc/v1/model-generator. Облікові дані API залишаються на сервері. Власна інтеграція має реалізувати рівноцінну обробку зберігання з автентифікацією; публічний API генератора не зберігає проєкти в Alter Product.

ТипОпис
ALTER_CHILD_HELLO / ALTER_PARENT_ACKДочірній iframe починає handshake з nonce; батьківська сторінка підтверджує той самий nonce.
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READYДочірній iframe запитує сеанс редагування model-generator; батьківська сторінка повертає авторизований токен.
ALTER_MODEL_GENERATOR_REQUESTДочірній iframe надсилає requestId, nonce і request, що містить method, path, data та responseType.
ALTER_MODEL_GENERATOR_RESPONSEБатьківська сторінка відповідає з тими самими requestId і nonce, а також полями status, data, headers та error за наявності помилки.
// Messages after ALTER_CHILD_HELLO / ALTER_PARENT_ACK agree on the nonce.
// Iframe -> parent:
const sessionRequest = {
  type: 'ALTER_CUSTOMIZER_INIT_SESSION',
  nonce: handshakeNonce,
  payload: {
    tool: 'model-generator', alterProductId: localProject.toolId, mode: 'edit'
  }
};

// Parent -> iframe, after the server authorizes the merchant and issues a token:
const sessionReady = {
  type: 'ALTER_CUSTOMIZER_SESSION_READY',
  nonce: handshakeNonce,
  token: session.token,
  tool: 'model-generator',
  cartKey: `model-generator:${localProject.id}`,
  mode: 'edit',
  localSession: false,
  adminSession: true
};
// Send only to the validated iframe's exact origin and source window.
// An authorized token and successful bootstrap are still required.

Під час збереження передаються expectedRevision, templateRevision, document і посилання на артефакти. Створюється незмінна ревізія; застарілий expectedRevision повертає HTTP 409. WordPress зберігає метадані у своїй базі даних, а файли — у каталозі uploads. JSON мініфікується та стискається за допомогою gzip, якщо стиснення зменшує його розмір.

// Example message from the iframe; savedSnapshot and artifact IDs come
// from the generator. The host checks origin/source/nonce/project permissions.
const message = {
  type: 'ALTER_MODEL_GENERATOR_REQUEST',
  requestId: crypto.randomUUID(),
  nonce: handshakeNonce,
  request: {
    method: 'POST',
    path: `/pattern-generator/projects/${projectUuid}/revisions`,
    data: {
      expectedRevision: loadedRevision,
      name: projectName,
      templateRevision,
      document: savedSnapshot,
      references: { artifactIds: savedArtifactIds }
    },
    responseType: 'json'
  }
};

Дія «Використати збережену модель у дизайні» публікує повну збережену ревізію в пов’язаному дизайні. Покупці бачать її через наявний Customizer, Configurator або Viewer зі звичними прив’язками товару й перевірками підписки. Редактор генератора залишається інструментом продавця. Посилання в замовленнях зберігають проєкт і ревізію, тому подальші правки не змінюють попередні замовлення автоматично.

Каталог ресурсів

Каталог ресурсів надає вихідні ресурси товарів, фони, оточення, елементи графічної бібліотеки, шаблони дизайнів і ресурси мокапів. Кінцеві точки списків повертають короткі описи, а детальні кінцеві точки — маніфести файлів.

ТипОпис
productsБазові ресурси товарів, зображення перегляду, 3D-моделі, описи матеріалів і текстур.
backgroundsСтатичні фони Viewer.
environmentsКарти оточення й зображення перегляду.
image_libraryРесурси графічної бібліотеки, зокрема графіка для певного магазину.
design_templatesПерегляди шаблонів дизайнів і посилання на файли шарів. Підтримує фільтр product_id.
mockupsРесурси генератора мокапів, фони й карти накладання. Підтримує фільтр product_id.

Приклад запиту (fetch)

const assets = await alterFetch('/assets?' + new URLSearchParams({
  type: 'products',
  limit: '20',
  offset: '0',
  search: 'mug'
}));

const details = await alterFetch('/assets/products/4');

const fileResponse = await fetch(
  'https://alterproduct.com/public-api/v1/assets/products/4/files/preview_medium',
  {
    headers: authHeaders
  }
);

const fileBlob = await fileResponse.blob();

Приклад відповіді

{
  "type": "products",
  "items": [
    {
      "assetType": "products",
      "assetId": "4",
      "title": "Mug 450ml",
      "slug": "product-4",
      "description": "Base product 4",
      "primaryRole": "preview_big",
      "fileCount": 8,
      "remoteVersion": "1.0",
      "thumbnail": {
        "role": "preview_small",
        "fileName": "product-4-preview-small.png",
        "mime": "image/png",
        "downloadPath": "/v1/assets/products/4/files/preview_small"
      },
      "metadata": {
        "productCategoryId": 2,
        "productModelCount": 1,
        "isDedicated": false
      }
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}

Імпорт дизайнів

Імпорт дизайнів надає доступ до дизайнів, розміщених в Alter, та їхніх файлів для зовнішніх виробничих процесів або міграції. API перевіряє наявність відповідного тарифу Business.

ПараметрОбов’язковоПодробиці
searchніШукає за назвою або ID дизайну.
offsetніТипово 0.
limitніТипово 20, максимум 100.

Приклад запиту (fetch)

const imports = await alterFetch('/design-imports?' + new URLSearchParams({
  limit: '20',
  offset: '0',
  search: 'mug'
}));

const details = await alterFetch('/design-imports/381');

const fileId = details.files[0].id;
const fileResponse = await fetch(
  `https://alterproduct.com/public-api/v1/design-imports/381/files/${fileId}`,
  {
    headers: authHeaders
  }
);

const fileBlob = await fileResponse.blob();

Приклад відповіді

{
  "eligible": true,
  "requiredPlan": "Business",
  "currentPlanName": "Business",
  "designs": [
    {
      "id": 381,
      "title": "Men's T-Shirt",
      "createdAt": "2026-01-03T23:55:05.000Z",
      "sourceStorefrontId": 12,
      "productId": 4,
      "productName": {
        "pl": "Koszulka",
        "en": "T-Shirt"
      },
      "storageMode": "alter",
      "runtimeStatus": {
        "designer": true,
        "viewer": true,
        "configurator": true,
        "customizer": true
      },
      "thumbnail": {
        "kind": "design-mockup",
        "fileId": "7df7...",
        "downloadPath": "/v1/design-imports/381/files/7df7..."
      }
    }
  ],
  "total": 1
}

Файли, шрифти й валюти

Публічні файли перегляду зручні для браузера. Захищені файли потребують підписаної URL-адреси або облікових даних API з files:read. Шрифти й валюти доступні через публічні кінцеві точки читання.

Кінцева точкаДоступПодробиці
/file/public/products/:productId/small.pngпублічнийМалий перегляд товару.
/file/public/products/:productId/medium.pngпублічнийСередній перегляд товару.
/file/public/products/:productId/big.pngпублічнийВеликий перегляд товару.
/file/protected/:keyпідписана URL-адреса або files:readЗахищений файл об’єктного сховища.
/fontsпублічнийМасив записів шрифтів.
/currenciesпублічнийМасив записів валют.

Приклад запиту (fetch)

const publicPreview = await fetch(
  'https://alterproduct.com/public-api/v1/file/public/products/4/medium.png'
);

const protectedFile = await fetch(
  'https://alterproduct.com/public-api/v1/file/protected/user_34/381/design/mockup-large.webp',
  {
    headers: authHeaders
  }
);

const fonts = await fetch('https://alterproduct.com/public-api/v1/fonts').then((res) => res.json());
const currencies = await fetch('https://alterproduct.com/public-api/v1/currencies').then((res) => res.json());

Приклад відповіді

[
  {
    "id": 1,
    "family": "Inter",
    "source": "google",
    "category": "sans-serif",
    "variants": ["regular", "600", "700"],
    "subsets": ["latin"],
    "version": "v19",
    "menu": "Inter",
    "files": {
      "regular": "https://..."
    }
  }
]
[
  {
    "id": 1,
    "code": "EUR",
    "name": "Euro",
    "symbol": "€",
    "decimalPlaces": 2
  }
]

Прив’язки середовища виконання

Прив’язки середовища виконання поєднують товари зовнішніх магазинів із дизайнами Alter Product і типами інструментів. Їх переважно використовують інтеграції WordPress/WooCommerce та складні серверні системи магазинів.

ПараметрОбов’язковоПодробиці
designIdніID дизайну Alter Product, що належить магазину.
externalProductIdтак, для синхронізаціїID зовнішнього товару, наприклад ID товару WooCommerce.
runtimeTypeтак, для синхронізаціїviewer, configurator або customizer.
statusніdraft, active, inactive, archived або legacy_active.
legacyStorefrontProductIdніНеобов’язковий ID застарілого зіставлення.
legacyBindingMetaніНеобов’язкові метадані JSON, наприклад manifestHash.

Приклад запиту (fetch)

await alterFetch('/runtime-bindings/sync-from-wordpress', {
  method: 'POST',
  body: JSON.stringify({
    bindings: [
      {
        externalProductId: 'wc_123',
        runtimeType: 'customizer',
        status: 'active',
        designId: 381,
        legacyBindingMeta: {
          manifestHash: 'a3b1...'
        }
      }
    ]
  })
});

await alterFetch('/runtime-bindings/42', {
  method: 'PATCH',
  body: JSON.stringify({
    status: 'inactive'
  })
});

await alterFetch('/runtime-bindings/42/activate', { method: 'POST' });
await alterFetch('/runtime-bindings/42/deactivate', { method: 'POST' });

wordpress_local

await alterFetch('/runtime-bindings/sync-from-wordpress', {
  method: 'POST',
  body: JSON.stringify({
    bindings: [
      {
        externalProductId: 'wc_123',
        runtimeType: 'viewer',
        status: 'active',
        externalDesign: {
          externalDesignKey: 'wp-design-381',
          productId: 4,
          title: 'WooCommerce local design',
          manifestUrl: 'https://yourstore.com/wp-content/uploads/alter/381/manifest.json',
          assetBaseUrl: 'https://yourstore.com/wp-content/uploads/alter/381/',
          manifestHash: 'a3b1...',
          sourceMeta: {
            pluginVersion: '1.2.0'
          }
        }
      }
    ]
  })
});

Приклад відповіді

{
  "message": "runtimeBinding.syncCompleted",
  "runtimeBindings": [
    {
      "id": 42,
      "designId": 381,
      "externalProductId": "wc_123",
      "runtimeType": "customizer",
      "status": "active"
    }
  ]
}

Обмін під час підключення WordPress

Кінцева точка обміну підключення WordPress приймає одноразовий код передачі й повертає плагіну облікові дані API. Вона не призначена для довільного створення облікових даних.

Приклад запиту (fetch)

const response = await fetch('https://alterproduct.com/public-api/v1/wp-connect/exchange', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    code: 'ONE_TIME_HANDOFF_CODE',
    storeUrl: 'https://yourstore.com/',
    siteOrigin: 'https://yourstore.com',
    codeVerifier: 'PKCE_CODE_VERIFIER_32_TO_128_CHARS'
  })
});

const credentials = await response.json();

Приклад відповіді

{
  "message": "wpConnect.exchange.ok",
  "accessKey": "generated-access-key",
  "accessToken": "generated-access-token",
  "storefrontId": 12
}

Помилки й обмеження частоти запитів

Більшість помилок контролерів нормалізуються у відповідь із code. Проміжні обробники автентифікації та обмеження частоти можуть натомість повертати відповідь із error.

// Controller error
{
  "code": "assetCatalog.invalidType"
}

// Auth middleware or rate limit
{
  "error": "Unauthorized"
}

{
  "error": "Too Many Requests"
}
ТипЛімітІнтервал
Глобальний600 запитів60 секунд
GET /auth/check60 запитів60 секунд
Читання замовлень/товарів300 запитів60 секунд
Запис замовлень/сеанси вбудовування/прив’язки середовища виконання120 запитів60 секунд
Читання ресурсів/імпортів дизайнів180 запитів60 секунд
Шрифти300 запитів60 секунд
Обмін підключення WP30 запитів60 секунд
GET /model-generator/*600 запитів60 секунд