Integrare Alter Product Public API

Public API este conceput pentru integrări între servere cu magazine, backenduri comerciale, module WordPress/WooCommerce și fluxuri externe de producție.

Autentificare și URL de bază

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

Creează credențiale API în panoul Setări e-commerce. Access Token este afișat o singură dată, deci salvează-l imediat în stocarea secretelor din backend.

Păstrează Access Key și Access Token pe server. Endpointurile autentificate resping apelurile provenite din browser care includ antetele Origin sau Referer.

Credențialele pot avea domenii de acces limitate. Folosește GET /auth/check pentru a verifica magazinul activ, funcționalitățile planului și domeniile de acces returnate pentru setul de credențiale.

x-alter-access-key: YOUR_API_KEY
x-alter-access-token: YOUR_API_TOKEN
ParametruObligatoriuDetalii
x-alter-access-keydaIdentificator public al setului de credențiale.
x-alter-access-tokendaToken secret asociat cheii de acces.
x-alter-client-fingerprintnuAmprentă stabilă opțională pentru limitarea solicitărilor de sesiuni de încorporare.
Authorizationdoar la execuțieToken Bearer returnat de POST /embed/session, folosit de /runtime/bootstrap.

Test de conexiune

Folosește endpointul de verificare a autentificării înainte de a activa sincronizarea sau încorporarea într-o integrare în producție.

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

Exemplu de solicitare (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);

Exemplu de răspuns

{
  "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
    }
  }
}

Funcția auxiliară de mai jos este folosită de celelalte exemple. Folosește fetch simplu și poate rula în Node.js 18+ sau în orice mediu de execuție de server care oferă 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;
}

Prezentare generală a endpointurilor

Tabelul de mai jos reflectă rutele publice montate în backend-public-api/app.js. Căile sunt afișate cu prefixul proxy public folosit de integrările externe.

MetodăEndpointDescriereAcces
GET/public-api/healthzVerificarea disponibilității serviciului.public
GET/public-api/v1/auth/checkValidează credențialele și returnează magazinul, domeniile de acces și funcționalitățile planului.orice set de credențiale autentificat
GET/public-api/v1/customer-ordersReturnează o listă paginată și filtrabilă a comenzilor clienților.orders:read
GET/public-api/v1/customer-orders/:idReturnează o comandă de client cu articole de produs configurate.orders:read
POST/public-api/v1/customer-orders/batchReturnează până la 100 de comenzi după ID.orders:read
PATCH/public-api/v1/customer-orders/:id/statusActualizează starea comenzii.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantityActualizează cantitățile pozițiilor selectate din comandă.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantity/allSetează o singură cantitate pentru fiecare articol dintr-o comandă.orders:write
DELETE/public-api/v1/customer-orders/:idȘterge o comandă de client care aparține proprietarului magazinului.orders:write
GET/public-api/v1/productsReturnează produse/designuri ale magazinului cu disponibilitatea încorporării și URL-urile media.products:read
GET/public-api/v1/products/:idReturnează un produs/design al magazinului.products:read
POST/public-api/v1/embed/sessionEmite un JWT cu durată scurtă de valabilitate pentru instrumentele încorporate, inclusiv generatorul de modele.embed:session:create
GET/public-api/v1/runtime/bootstrapDetermină contextul de execuție dintr-un JWT de încorporare.token de încorporare Bearer
GET/public-api/v1/assetsListează elementele catalogului de resurse pentru tipul solicitat.orice set de credențiale autentificat
GET/public-api/v1/assets/:type/:assetIdReturnează un manifest de resursă cu rolurile fișierelor descărcabile.orice set de credențiale autentificat
GET/public-api/v1/assets/:type/:assetId/files/:roleDescarcă un fișier de resursă după rol.orice set de credențiale autentificat
GET/public-api/v1/design-importsListează designurile găzduite pe Alter care pot fi importate.set de credențiale autentificat, plan Business obligatoriu
GET/public-api/v1/design-imports/:idReturnează un payload de import de design și descriptori de fișiere.set de credențiale autentificat, plan Business obligatoriu
GET/public-api/v1/design-imports/:id/files/:fileIdDescarcă un fișier dintr-un descriptor de import de design.set de credențiale autentificat, plan Business obligatoriu
GET/public-api/v1/file/public/products/:productId/:sizeReturnează o previzualizare publică a produsului. Dimensiunea trebuie să fie small.png, medium.png sau big.png.public
GET/public-api/v1/file/protected/:keyReturnează un fișier protejat după cheia de stocare.URL semnat sau files:read
GET/public-api/v1/fontsReturnează toate fonturile disponibile.public
GET/public-api/v1/currenciesReturnează toate monedele.public
POST/public-api/v1/runtime-bindings/sync-from-wordpressCreează sau actualizează asocieri de execuție din mapările produselor WordPress.orice set de credențiale autentificat
PATCH/public-api/v1/runtime-bindings/:idModifică parțial o asociere de execuție.orice set de credențiale autentificat
POST/public-api/v1/runtime-bindings/:id/activateActivează o asociere de execuție.orice set de credențiale autentificat
POST/public-api/v1/runtime-bindings/:id/deactivateDezactivează o asociere de execuție.orice set de credențiale autentificat
POST/public-api/v1/wp-connect/exchangeSchimbă un cod de transfer al conectării automate WordPress cu credențiale API.cod de transfer de unică folosință
GET/public-api/v1/model-generator/catalogListează produsele vizibile ale generatorului, configurațiile și reviziile șabloanelor.embed:session:create
GET/public-api/v1/model-generator/modelsListează modelele cu descriptori care fixează reviziile sursă ale generatorului pentru import.embed:session:create
GET/public-api/v1/model-generator/designer-catalogReturnează catalogul de modele ale generatorului folosit de Designer.embed:session:create
GET/public-api/v1/model-generator/projectsListează proiectele de generator ale proprietarului și cele disponibile global.embed:session:create
GET/public-api/v1/model-generator/projects/:projectIdReturnează cea mai recentă revizie a proiectului sau revizia selectată, șablonul și manifestul fișierelor.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/revisions/:revisionReturnează cea mai recentă revizie a proiectului sau revizia selectată, șablonul și manifestul fișierelor.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/artifacts/:artifactIdDescarcă un artefact după verificarea accesului la proiectul său.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/templateReturnează un document de șablon accesibil pentru revizia de configurație selectată.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/importReturnează pachetul de import al șablonului împreună cu fișierele de dependențe.embed:session:create
GET/public-api/v1/model-generator/mannequinsReturnează ambele manechine și descriptorii resurselor lor.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assetsListează resursele bibliotecii de texturi sau fundaluri cu fișierele care pot fi importate.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assets/:assetIdReturnează o resursă de textură sau fundal împreună cu fișierele care pot fi importate.embed:session:create
GET/public-api/v1/model-generator/public-files/:keyDescarcă un fișier de dependență permis al generatorului.embed:session:create

Comenzile clienților

Endpointurile comenzilor de client permit unui magazin extern să citească articolele configurate, să actualizeze cantitățile, să treacă o comandă prin stările de procesare și să elimine comenzile abandonate.

ParametruObligatoriuDetalii
namenuCaută după numele designului și ID-ul numeric al comenzii.
category_idnuFiltrează după ID-ul categoriei de produs.
order_statusnuUna dintre stările permise ale comenzii.
offsetnuImplicit 0. Trebuie să fie >= 0.
limitnuImplicit 9 pentru acest controler, maximum 50.
order_bynuid, created_at sau design_name.
directionnuASC sau DESC.

Exemplu de solicitare (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]
  })
});

Valori permise

StareDescriere
shopping_cartFluxul coșului; clientul încă poate edita configurația.
editableComanda rămâne editabilă de către client.
paidComanda este plătită și pregătită pentru procesare.
processingComanda este în procesare.
completedComanda a fost finalizată.
cancelledComanda a fost anulată.

Exemplu de solicitare (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'
});

Exemplu de răspuns

{
  "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" }
  }
}

Produsele magazinului

Endpointurile produselor returnează designuri ale magazinului care pot fi încorporate ca experiențe Viewer, Configurator sau Customizer.

ParametruObligatoriuDetalii
namenuCaută după numele produsului/designului.
customizernutrue sau false.
offsetnuImplicit 0. Trebuie să fie >= 0.
limitnuImplicit 9, maximum 50.
order_bynuid, name sau created_at.
directionnuASC sau DESC.

Exemplu de solicitare (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');

Exemplu de răspuns

{
  "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
  }
}

Sesiuni de încorporare și inițializarea mediului de execuție

Creează pe server un token de încorporare de scurtă durată, transmite-l către iframe/mediul de execuție, apoi permite mediului să apeleze bootstrap cu un token Bearer.

ParametruObligatoriuDetalii
runtimeBindingIdrecomandatIdentificator preferat pentru asocierile de execuție active.
toolobligatoriu fără runtimeBindingIddesigner | viewer | configurator | customizer | model-generator
toolIdtool: model-generatorID numeric pozitiv al proiectului local al generatorului, nu UUID-ul său sau ID-ul produsului WooCommerce.
origindaOriginea în care este afișat conținutul încorporat, de exemplu https://yourstore.com.
designIdun identificatorID-ul designului Alter Product. Nu combina cu orderId.
orderIdun identificatorID-ul comenzii Customizer. Valabil doar pentru customizer.
cartKey + cartModenuContext de coș exclusiv pentru Customizer. cartMode este view sau edit.

Exemplu de solicitare (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 });

Note

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
  })
});

Exemplu de răspuns

{
  "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
}

Generator de modele 3D

Endpointurile de import ale generatorului permit doar citirea în comunicarea dintre servere. Necesită antetele API standard, permisiunea embed:session:create și un plan activ. Autorizarea importului nu creează o sesiune de editor și nu consumă limita lunară a acesteia. Deschiderea editorului folosește același contor monthlyEmbedTokenLimit ca celelalte instrumente încorporate.

Găsirea și importarea modelelor cu generator

Folosește /model-generator/models pentru a lista modelele disponibile cu generatoare. Descriptorul generator fixează valorile projectId, revision, configurationId, templateRevision, productId și productModel3dId. Urmează importPath pentru a prelua exact acea revizie sursă. Manifestele resurselor de produs expun și generators, precum și descriptorul generator al fiecărui model. Șabloanele pot fi importate separat, după configurație și revizie.

Filtre de catalog

EndpointDetalii
/model-generator/modelsLista de modele: name (sau q), categoryId, scope (all, own, global), limit (1–50) și offset.
/model-generator/catalogCatalogul de șabloane: generatorType, productId, audience, q, templateKey, configurationId, limit și offset.
/model-generator/projectsLista de proiecte: configurationId, q, scope (all, own, global), limit și offset. Proxy-ul public folosește implicit scope all.
/model-generator/image-libraries/:kind/assetsBiblioteci de texturi și fundaluri: kind este texture sau background; q, category și mapType filtrează resursele disponibile.

Un import de proiect conține document, revision, template și un manifest files. Fiecare fișier furnizează un path sub /v1/model-generator/; adaugă /public-api înaintea lui când descarci din Alter Product. Copiază fișierele necesare în propriul spațiu de stocare și înlocuiește referințele sursă cu referințe locale. Importă manechinele și bibliotecile de texturi prin endpointurile lor de catalog; public-files permite numai căile de resurse aprobate, iar șabloanele trebuie să treacă verificările de acces la configurație și revizie.

Exemplu de solicitare (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 });

Sesiunea editorului și stocarea locală

Creează sesiunea editorului cu tool: model-generator, un toolId numeric pozitiv care identifică proiectul local al generatorului (nu UUID-ul acestuia sau ID-ul produsului WooCommerce) și originea permisă a magazinului. Nu transmite designId, orderId, runtimeBindingId sau câmpuri de coș pentru acest instrument. UUID-ul proiectului generatorului este un identificator separat. Transmite tokenul primit prin handshake-ul iframe; runtime bootstrap returnează contextul generatorului cu 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);

Exemplu de răspuns

{
  "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.

Mesaje iframe folosite de puntea WordPress

Pluginul WordPress găzduiește puntea de stocare și verifică permisiunile de administrator sau manager WooCommerce. Validează originea iframe-ului, fereastra sursă, nonce, identificatorul cererii și căile de proiect permise. Puntea trimite citirile și scrierile locale către /wp-json/alter-wc/v1/model-generator. Datele de acces API rămân pe server. O integrare personalizată trebuie să implementeze un mecanism echivalent de stocare autentificată; API-ul public al generatorului nu salvează proiecte în Alter Product.

TipDescriere
ALTER_CHILD_HELLO / ALTER_PARENT_ACKIframe-ul inițiază handshake-ul cu un nonce; pagina părinte confirmă același nonce.
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READYIframe-ul solicită o sesiune de editare model-generator; pagina părinte returnează tokenul autorizat.
ALTER_MODEL_GENERATOR_REQUESTIframe-ul trimite requestId, nonce și request care conține method, path, data și responseType.
ALTER_MODEL_GENERATOR_RESPONSEPagina părinte răspunde cu același requestId și nonce, împreună cu status, data, headers și eventualul 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.

O salvare transmite expectedRevision, templateRevision, document și referințe la artefacte. Creează o revizie imuabilă; o valoare expectedRevision neactualizată returnează HTTP 409. WordPress stochează metadatele în baza sa de date, iar fișierele în directorul uploads. JSON este minificat și comprimat cu gzip atunci când comprimarea îi reduce dimensiunea.

// 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'
  }
};

Acțiunea Folosește modelul salvat în design publică o revizie salvată completă într-un design asociat. Clienții o văd apoi prin Customizer, Configurator sau Viewer, cu asocierile obișnuite ale produselor și verificările de abonament. Editorul generatorului rămâne un instrument al comerciantului. Legăturile comenzilor păstrează proiectul și revizia salvate, astfel încât modificările ulterioare să nu schimbe automat comenzile anterioare.

Catalog de resurse

Catalogul de resurse expune resursele sursă ale produselor, fundaluri, medii, elemente ale bibliotecii grafice, șabloane de design și resurse pentru machete. Endpointurile de listare returnează descriptori ușori; cele de detaliu includ manifeste de fișiere.

TipDescriere
productsResurse de bază ale produsului, previzualizări, modele 3D și descriptori de materiale și texturi.
backgroundsFundaluri statice Viewer.
environmentsHărți de mediu și imagini de previzualizare.
image_libraryResurse ale bibliotecii grafice, inclusiv grafică limitată la magazin.
design_templatesPrevizualizări ale șabloanelor de design și referințe la fișierele straturilor. Acceptă filtrul product_id.
mockupsResurse ale generatorului de machete, fundaluri și hărți de suprapunere. Acceptă filtrul product_id.

Exemplu de solicitare (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();

Exemplu de răspuns

{
  "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
}

Importuri de designuri

Importurile de designuri expun designuri găzduite pe Alter și fișierele lor pentru fluxuri externe de producție sau migrare. Eligibilitatea planului Business este verificată de API.

ParametruObligatoriuDetalii
searchnuCaută după titlul sau ID-ul designului.
offsetnuImplicit 0.
limitnuImplicit 20, maximum 100.

Exemplu de solicitare (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();

Exemplu de răspuns

{
  "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
}

Fișiere, fonturi și monede

Fișierele publice de previzualizare sunt compatibile cu browserele. Fișierele protejate necesită un URL semnat sau un set de credențiale API cu files:read. Fonturile și monedele sunt endpointuri publice de citire.

EndpointAccesDetalii
/file/public/products/:productId/small.pngpublicPrevizualizare mică a produsului.
/file/public/products/:productId/medium.pngpublicPrevizualizare medie a produsului.
/file/public/products/:productId/big.pngpublicPrevizualizare mare a produsului.
/file/protected/:keyURL semnat sau files:readFișier protejat în stocarea de obiecte.
/fontspublicArray de înregistrări de fonturi.
/currenciespublicArray de înregistrări de monede.

Exemplu de solicitare (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());

Exemplu de răspuns

[
  {
    "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
  }
]

Asocieri de execuție

Asocierile de execuție conectează produse comerciale externe la designuri și tipuri de execuție Alter Product. Sunt folosite în principal de integrările WordPress/WooCommerce și de backendurile avansate ale magazinelor.

ParametruObligatoriuDetalii
designIdnuID-ul designului Alter Product care aparține magazinului.
externalProductIdda pentru sincronizareID-ul produsului extern, de exemplu un ID de produs WooCommerce.
runtimeTypeda pentru sincronizareviewer, configurator sau customizer.
statusnudraft, active, inactive, archived sau legacy_active.
legacyStorefrontProductIdnuID opțional al mapării vechi.
legacyBindingMetanuMetadate JSON opționale, de exemplu manifestHash.

Exemplu de solicitare (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'
          }
        }
      }
    ]
  })
});

Exemplu de răspuns

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

Schimbul codului de conectare WordPress

Endpointul pentru schimbul codului de conectare WordPress consumă un cod de transfer de unică folosință și returnează credențiale API modulului. Nu este un endpoint general pentru crearea credențialelor.

Exemplu de solicitare (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();

Exemplu de răspuns

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

Erori și limite de solicitări

Majoritatea erorilor de controler sunt normalizate într-un răspuns code. Middleware-ul de autentificare și limitatoarele de solicitări pot returna în schimb un răspuns error.

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

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

{
  "error": "Too Many Requests"
}
TipLimităFereastră
Global600 de solicitări60 de secunde
GET /auth/check60 de solicitări60 de secunde
Citire comenzi/produse300 de solicitări60 de secunde
Scriere comenzi/sesiuni de încorporare/asocieri de execuție120 de solicitări60 de secunde
Citire resurse/importuri de designuri180 de solicitări60 de secunde
Fonturi300 de solicitări60 de secunde
Schimb de conectare WP30 de solicitări60 de secunde
GET /model-generator/*600 de solicitări60 de secunde