Integrazione della Public API di Alter Product

La Public API è progettata per integrazioni tra server con negozi, backend commerciali, plugin WordPress/WooCommerce e flussi di produzione esterni.

Autenticazione e URL base

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

Crea le credenziali API nel pannello Impostazioni e-commerce. L'Access Token viene mostrato una sola volta: salvalo subito nell'archivio dei segreti del backend.

Conserva Access Key e Access Token sul server. Gli endpoint autenticati rifiutano le chiamate provenienti dal browser che includono gli header Origin o Referer.

Le credenziali possono avere ambiti limitati. Usa GET /auth/check per verificare il negozio attivo, le funzionalità del piano e gli ambiti restituiti per la credenziale.

x-alter-access-key: YOUR_API_KEY
x-alter-access-token: YOUR_API_TOKEN
ParametroObbligatorioDettagli
x-alter-access-keyIdentificatore pubblico della credenziale.
x-alter-access-tokenToken segreto associato alla chiave di accesso.
x-alter-client-fingerprintnoImpronta stabile facoltativa per limitare le richieste di sessioni di incorporamento.
Authorizationsolo runtimeToken Bearer restituito da POST /embed/session, usato da /runtime/bootstrap.

Test di connessione

Usa l'endpoint di verifica dell'autenticazione prima di attivare sincronizzazione o incorporamento in un'integrazione in produzione.

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

Esempio di richiesta (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);

Esempio di risposta

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

La funzione ausiliaria seguente è usata negli altri esempi. Usa fetch semplice e può essere eseguita in Node.js 18+ o in qualsiasi runtime server che offra 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;
}

Panoramica degli endpoint

La tabella seguente rispecchia le route pubbliche montate in backend-public-api/app.js. I percorsi sono mostrati con il prefisso del proxy pubblico usato dalle integrazioni esterne.

MetodoEndpointDescrizioneAccesso
GET/public-api/healthzVerifica della disponibilità del servizio.pubblico
GET/public-api/v1/auth/checkConvalida le credenziali e restituisce negozio, ambiti e funzionalità del piano.qualsiasi credenziale autenticata
GET/public-api/v1/customer-ordersRestituisce un elenco paginato e filtrabile degli ordini dei clienti.orders:read
GET/public-api/v1/customer-orders/:idRestituisce un singolo ordine cliente con articoli di prodotto configurati.orders:read
POST/public-api/v1/customer-orders/batchRestituisce fino a 100 ordini tramite ID.orders:read
PATCH/public-api/v1/customer-orders/:id/statusAggiorna lo stato dell'ordine.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantityAggiorna le quantità delle righe d'ordine selezionate.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantity/allImposta un'unica quantità per ogni articolo di un ordine.orders:write
DELETE/public-api/v1/customer-orders/:idElimina un ordine cliente appartenente al proprietario del negozio.orders:write
GET/public-api/v1/productsRestituisce prodotti/design del negozio con disponibilità di incorporamento e URL dei contenuti multimediali.products:read
GET/public-api/v1/products/:idRestituisce un prodotto/design del negozio.products:read
POST/public-api/v1/embed/sessionEmette un JWT di breve durata per gli strumenti incorporati, incluso il generatore di modelli.embed:session:create
GET/public-api/v1/runtime/bootstrapRisolve il contesto runtime da un JWT di incorporamento.token di incorporamento Bearer
GET/public-api/v1/assetsElenca gli elementi del catalogo delle risorse per il tipo richiesto.qualsiasi credenziale autenticata
GET/public-api/v1/assets/:type/:assetIdRestituisce un manifesto della risorsa con i ruoli dei file scaricabili.qualsiasi credenziale autenticata
GET/public-api/v1/assets/:type/:assetId/files/:roleScarica un file di risorsa in base al ruolo.qualsiasi credenziale autenticata
GET/public-api/v1/design-importsElenca i design ospitati su Alter disponibili per l'importazione.credenziale autenticata, piano Business richiesto
GET/public-api/v1/design-imports/:idRestituisce un payload di importazione del design e descrittori dei file.credenziale autenticata, piano Business richiesto
GET/public-api/v1/design-imports/:id/files/:fileIdScarica un file da un descrittore di importazione del design.credenziale autenticata, piano Business richiesto
GET/public-api/v1/file/public/products/:productId/:sizeRestituisce un'anteprima pubblica del prodotto. La dimensione deve essere small.png, medium.png o big.png.pubblico
GET/public-api/v1/file/protected/:keyRestituisce un file protetto tramite la chiave di archiviazione.URL firmato o files:read
GET/public-api/v1/fontsRestituisce tutti i font disponibili.pubblico
GET/public-api/v1/currenciesRestituisce tutte le valute.pubblico
POST/public-api/v1/runtime-bindings/sync-from-wordpressCrea o aggiorna associazioni runtime a partire dalle mappature dei prodotti WordPress.qualsiasi credenziale autenticata
PATCH/public-api/v1/runtime-bindings/:idModifica parzialmente un'associazione runtime.qualsiasi credenziale autenticata
POST/public-api/v1/runtime-bindings/:id/activateAttiva un'associazione runtime.qualsiasi credenziale autenticata
POST/public-api/v1/runtime-bindings/:id/deactivateDisattiva un'associazione runtime.qualsiasi credenziale autenticata
POST/public-api/v1/wp-connect/exchangeScambia un codice di passaggio della connessione automatica WordPress con credenziali API.codice di passaggio monouso
GET/public-api/v1/model-generator/catalogElenca i prodotti del generatore, le configurazioni e le revisioni dei template visibili.embed:session:create
GET/public-api/v1/model-generator/modelsElenca i modelli con descrittori delle sorgenti del generatore fissati a revisioni specifiche per l’importazione.embed:session:create
GET/public-api/v1/model-generator/designer-catalogRestituisce il catalogo dei modelli del generatore utilizzato da Designer.embed:session:create
GET/public-api/v1/model-generator/projectsElenca i progetti del generatore del proprietario e quelli disponibili globalmente.embed:session:create
GET/public-api/v1/model-generator/projects/:projectIdRestituisce la revisione più recente o selezionata del progetto, il template e il manifest dei file.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/revisions/:revisionRestituisce la revisione più recente o selezionata del progetto, il template e il manifest dei file.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/artifacts/:artifactIdScarica un artefatto dopo aver verificato l’accesso al relativo progetto.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/templateRestituisce un documento di template accessibile per la revisione di configurazione selezionata.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/importRestituisce il pacchetto di importazione del template con i file delle dipendenze.embed:session:create
GET/public-api/v1/model-generator/mannequinsRestituisce entrambi i manichini e i descrittori delle loro risorse.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assetsElenca le risorse delle librerie di texture o sfondi con i file importabili.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assets/:assetIdRestituisce una singola risorsa di texture o sfondo con i relativi file importabili.embed:session:create
GET/public-api/v1/model-generator/public-files/:keyScarica un file di dipendenza consentito del generatore.embed:session:create

Ordini dei clienti

Gli endpoint degli ordini dei clienti consentono a un negozio esterno di leggere gli articoli configurati, aggiornare le quantità, far avanzare un ordine tra gli stati di evasione ed eliminare ordini abbandonati.

ParametroObbligatorioDettagli
namenoCerca per nome del design e ID numerico dell'ordine.
category_idnoFiltra per ID della categoria del prodotto.
order_statusnoUno degli stati dell'ordine consentiti.
offsetnoPredefinito 0. Deve essere >= 0.
limitnoPredefinito 9 per questo controller, massimo 50.
order_bynoid, created_at o design_name.
directionnoASC o DESC.

Esempio di richiesta (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 consentiti

StatoDescrizione
shopping_cartFlusso del carrello; il cliente può ancora modificare la configurazione.
editableL'ordine resta modificabile dal cliente.
paidL'ordine è pagato e pronto per l'evasione.
processingL'ordine è in fase di evasione.
completedL'ordine è stato evaso.
cancelledL'ordine è stato annullato.

Esempio di richiesta (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'
});

Esempio di risposta

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

Prodotti del negozio

Gli endpoint dei prodotti restituiscono design del negozio incorporabili come esperienze Viewer, Configurator o Customizer.

ParametroObbligatorioDettagli
namenoCerca per nome del prodotto/design.
customizernotrue o false.
offsetnoPredefinito 0. Deve essere >= 0.
limitnoPredefinito 9, massimo 50.
order_bynoid, name o created_at.
directionnoASC o DESC.

Esempio di richiesta (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');

Esempio di risposta

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

Sessioni di incorporamento e inizializzazione del runtime

Crea un token di incorporamento di breve durata dal server, passalo all'iframe/runtime e lascia che il runtime chiami bootstrap con un token Bearer.

ParametroObbligatorioDettagli
runtimeBindingIdconsigliatoIdentificatore preferito per le associazioni runtime attive.
toolobbligatorio senza runtimeBindingIddesigner | viewer | configurator | customizer | model-generator
toolIdtool: model-generatorID numerico positivo del progetto locale del generatore, non il suo UUID né l’ID del prodotto WooCommerce.
originOrigine in cui viene mostrato il contenuto incorporato, ad esempio https://yourstore.com.
designIdun identificatoreID del design Alter Product. Non combinare con orderId.
orderIdun identificatoreID dell'ordine Customizer. Valido solo per customizer.
cartKey + cartModenoContesto del carrello esclusivo del Customizer. cartMode è view o edit.

Esempio di richiesta (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
  })
});

Esempio di risposta

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

Generatore di modelli 3D

Gli endpoint di importazione del generatore accettano solo richieste di lettura tra server. Richiedono gli header API standard, lo scope embed:session:create e un piano attivo. L’autorizzazione all’importazione non crea una sessione dell’editor e non ne consuma la quota mensile. L’apertura dell’editor utilizza lo stesso contatore monthlyEmbedTokenLimit degli altri strumenti incorporati.

Trovare e importare modelli con generatore

Usa /model-generator/models per elencare i modelli disponibili con generatore. Il descrittore generator fissa projectId, revision, configurationId, templateRevision, productId e productModel3dId. Segui il suo importPath per recuperare esattamente quella revisione sorgente. I manifest delle risorse di prodotto espongono anche generators e il descrittore generator di ogni modello. I template possono essere importati separatamente in base a configurazione e revisione.

Filtri dei cataloghi

EndpointDettagli
/model-generator/modelsElenco dei modelli: name (o q), categoryId, scope (all, own, global), limit (1–50) e offset.
/model-generator/catalogCatalogo dei template: generatorType, productId, audience, q, templateKey, configurationId, limit e offset.
/model-generator/projectsElenco dei progetti: configurationId, q, scope (all, own, global), limit e offset. Il proxy pubblico imposta scope su all per impostazione predefinita.
/model-generator/image-libraries/:kind/assetsLibrerie di texture e sfondi: kind è texture o background; q, category e mapType filtrano le risorse disponibili.

L’importazione di un progetto contiene document, revision, template e un manifest files. Ogni file fornisce un path sotto /v1/model-generator/; anteponi /public-api quando lo scarichi da Alter Product. Copia i file necessari nel tuo spazio di archiviazione e sostituisci i riferimenti sorgente con riferimenti locali. Importa manichini e librerie di texture tramite i rispettivi endpoint di catalogo; public-files è limitato ai percorsi di risorse consentiti e i template devono superare i controlli di accesso per la propria configurazione e revisione.

Esempio di richiesta (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 });

Sessione dell’editor e archiviazione locale

Crea la sessione dell’editor con tool: model-generator, un toolId numerico positivo che identifichi il progetto locale del generatore (non il suo UUID né l’ID del prodotto WooCommerce) e l’origine consentita del negozio. Per questo strumento non inviare designId, orderId, runtimeBindingId o campi del carrello. L’UUID del progetto del generatore è un identificatore separato. Trasmetti il token ricevuto tramite l’handshake dell’iframe; il bootstrap del runtime restituisce il contesto del generatore con 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);

Esempio di risposta

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

Messaggi iframe utilizzati dal ponte WordPress

Il plugin WordPress ospita il ponte di archiviazione e verifica i permessi di amministratore o gestore WooCommerce. Convalida l’origine dell’iframe, la finestra sorgente, il nonce, l’ID della richiesta e i percorsi di progetto consentiti. Il ponte invia le letture e le scritture locali a /wp-json/alter-wc/v1/model-generator. Le credenziali API rimangono sul server. Un’integrazione personalizzata deve implementare una gestione autenticata dell’archiviazione equivalente; l’API pubblica del generatore non salva progetti su Alter Product.

TipoDescrizione
ALTER_CHILD_HELLO / ALTER_PARENT_ACKL’iframe avvia l’handshake con un nonce; la pagina principale conferma lo stesso nonce.
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READYL’iframe richiede una sessione di modifica model-generator; la pagina principale restituisce il token autorizzato.
ALTER_MODEL_GENERATOR_REQUESTL’iframe invia requestId, nonce e request contenente method, path, data e responseType.
ALTER_MODEL_GENERATOR_RESPONSELa pagina principale risponde con gli stessi requestId e nonce, oltre a status, data, headers ed eventuale 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.

Il salvataggio invia expectedRevision, templateRevision, document e i riferimenti agli artefatti. Crea una revisione immutabile; un valore expectedRevision non aggiornato restituisce HTTP 409. WordPress memorizza i metadati nel proprio database e i file nella directory uploads. Il JSON viene minificato e compresso con gzip quando la compressione ne riduce le dimensioni.

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

Usa il modello salvato nel design pubblica una revisione salvata completa in un design di prodotto collegato. I clienti la visualizzano poi tramite Customizer, Configurator o Viewer esistenti, con le consuete associazioni di prodotto e verifiche dell’abbonamento. L’editor del generatore rimane uno strumento per il commerciante. I collegamenti degli ordini conservano il progetto e la revisione salvati, in modo che le modifiche successive non alterino silenziosamente gli ordini precedenti.

Catalogo delle risorse

Il catalogo delle risorse espone risorse originali dei prodotti, sfondi, ambienti, elementi della libreria grafica, modelli di design e risorse mockup. Gli endpoint di elenco restituiscono descrittori leggeri; quelli di dettaglio includono manifesti dei file.

TipoDescrizione
productsRisorse base del prodotto, anteprime, modelli 3D e descrittori di materiali e texture.
backgroundsSfondi statici del Viewer.
environmentsMappe ambientali e immagini di anteprima.
image_libraryRisorse della libreria grafica, incluse grafiche limitate al negozio.
design_templatesAnteprime dei modelli di design e riferimenti ai file dei livelli. Supporta il filtro product_id.
mockupsRisorse del generatore di mockup, sfondi e mappe di sovrapposizione. Supporta il filtro product_id.

Esempio di richiesta (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();

Esempio di risposta

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

Importazioni di design

Le importazioni di design espongono i design ospitati su Alter e i relativi file per flussi esterni di produzione o migrazione. L'API verifica l'idoneità del piano Business.

ParametroObbligatorioDettagli
searchnoCerca per titolo o ID del design.
offsetnoPredefinito 0.
limitnoPredefinito 20, massimo 100.

Esempio di richiesta (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();

Esempio di risposta

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

File, font e valute

I file pubblici di anteprima sono adatti ai browser. I file protetti richiedono un URL firmato o una credenziale API con files:read. Font e valute sono endpoint pubblici di lettura.

EndpointAccessoDettagli
/file/public/products/:productId/small.pngpubblicoAnteprima piccola del prodotto.
/file/public/products/:productId/medium.pngpubblicoAnteprima media del prodotto.
/file/public/products/:productId/big.pngpubblicoAnteprima grande del prodotto.
/file/protected/:keyURL firmato o files:readFile protetto nell'archiviazione a oggetti.
/fontspubblicoArray di record dei font.
/currenciespubblicoArray di record delle valute.

Esempio di richiesta (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());

Esempio di risposta

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

Associazioni runtime

Le associazioni runtime collegano prodotti commerciali esterni a design e tipi di runtime Alter Product. Sono usate soprattutto dalle integrazioni WordPress/WooCommerce e dai backend avanzati dei negozi.

ParametroObbligatorioDettagli
designIdnoID del design Alter Product appartenente al negozio.
externalProductIdsì per la sincronizzazioneID del prodotto esterno, ad esempio un ID di prodotto WooCommerce.
runtimeTypesì per la sincronizzazioneviewer, configurator o customizer.
statusnodraft, active, inactive, archived o legacy_active.
legacyStorefrontProductIdnoID facoltativo della mappatura legacy.
legacyBindingMetanoMetadati JSON facoltativi, ad esempio manifestHash.

Esempio di richiesta (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'
          }
        }
      }
    ]
  })
});

Esempio di risposta

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

Scambio del codice di connessione WordPress

L'endpoint di scambio della connessione WordPress consuma un codice di passaggio monouso e restituisce le credenziali API al plugin. Non è un endpoint generico per creare credenziali.

Esempio di richiesta (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();

Esempio di risposta

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

Errori e limiti di richieste

La maggior parte degli errori dei controller viene normalizzata in una risposta code. Il middleware di autenticazione e i limitatori di richieste possono invece restituire una risposta error.

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

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

{
  "error": "Too Many Requests"
}
TipoLimiteFinestra
Globale600 richieste60 secondi
GET /auth/check60 richieste60 secondi
Lettura di ordini/prodotti300 richieste60 secondi
Scrittura di ordini/sessioni di incorporamento/associazioni runtime120 richieste60 secondi
Lettura di risorse/importazioni di design180 richieste60 secondi
Font300 richieste60 secondi
Scambio di connessione WP30 richieste60 secondi
GET /model-generator/*600 richieste60 secondi