Integration med Alter Product Public API

Public API er beregnet til integrationer mellem servere med webshops, e-handelsbackends, WordPress/WooCommerce-plugins og eksterne produktionsforløb.

Godkendelse og basis-URL

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

Opret API-legitimationsoplysninger i panelet med e-handelsindstillinger. Access Token vises kun én gang, så gem det straks i din backends lager til hemmeligheder.

Opbevar Access Key og Access Token på din server. Godkendte endpoints afviser browserkald med Origin- eller Referer-headere.

Legitimationsoplysninger kan have begrænset adgangsomfang. Brug GET /auth/check til at kontrollere den aktive butik, planfunktioner og det adgangsomfang, der returneres for oplysningerne.

x-alter-access-key: YOUR_API_KEY
x-alter-access-token: YOUR_API_TOKEN
ParameterPåkrævetDetaljer
x-alter-access-keyjaOffentlig identifikator for legitimationsoplysninger.
x-alter-access-tokenjaHemmeligt token, der hører til adgangsnøglen.
x-alter-client-fingerprintnejValgfrit stabilt fingeraftryk til begrænsning af indlejringssessioners anmodninger.
Authorizationkun runtimeBearer-token returneret af POST /embed/session, bruges af /runtime/bootstrap.

Forbindelsestest

Brug endpointet til godkendelseskontrol, før du aktiverer synkronisering eller indlejring i en produktionsintegration.

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

Eksempel på anmodning (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);

Eksempel på svar

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

Hjælpefunktionen nedenfor bruges i de øvrige eksempler. Den bruger almindelig fetch og kan køre i Node.js 18+ eller ethvert serverruntime med 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;
}

Endpointoversigt

Tabellen nedenfor afspejler de offentlige ruter i backend-public-api/app.js. Stierne vises med det offentlige proxyprefix, som eksterne integrationer bruger.

MetodeEndpointBeskrivelseAdgang
GET/public-api/healthzSundhedskontrol af tjenesten.offentlig
GET/public-api/v1/auth/checkValiderer legitimationsoplysninger og returnerer butik, adgangsomfang og planfunktioner.vilkårlige godkendte legitimationsoplysninger
GET/public-api/v1/customer-ordersReturnerer en sideinddelt og filtrerbar liste over kundeordrer.orders:read
GET/public-api/v1/customer-orders/:idReturnerer en kundeordre med konfigurerede produktlinjer.orders:read
POST/public-api/v1/customer-orders/batchReturnerer op til 100 ordrer efter ID.orders:read
PATCH/public-api/v1/customer-orders/:id/statusOpdaterer ordrestatus.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantityOpdaterer antal for valgte ordredetaljer.orders:write
PATCH/public-api/v1/customer-orders/:orderId/quantity/allAngiver samme antal for hver vare i en ordre.orders:write
DELETE/public-api/v1/customer-orders/:idSletter en kundeordre, der tilhører butiksejeren.orders:write
GET/public-api/v1/productsReturnerer butiksprodukter/designs med indlejringstilgængelighed og medie-URL'er.products:read
GET/public-api/v1/products/:idReturnerer ét butiksprodukt/design.products:read
POST/public-api/v1/embed/sessionUdsteder et kortvarigt JWT til indlejrede værktøjer, herunder modelgeneratoren.embed:session:create
GET/public-api/v1/runtime/bootstrapUdleder runtimekontekst fra et indlejrings-JWT.Bearer-token til indlejring
GET/public-api/v1/assetsViser ressourcekatalogets elementer for den ønskede type.vilkårlige godkendte legitimationsoplysninger
GET/public-api/v1/assets/:type/:assetIdReturnerer et ressourcemanifest med filroller, der kan downloades.vilkårlige godkendte legitimationsoplysninger
GET/public-api/v1/assets/:type/:assetId/files/:roleDownloader en ressourcefil efter rolle.vilkårlige godkendte legitimationsoplysninger
GET/public-api/v1/design-importsViser importerbare designs hostet hos Alter.godkendte legitimationsoplysninger, Business-plan påkrævet
GET/public-api/v1/design-imports/:idReturnerer payload og filbeskrivelser til designimport.godkendte legitimationsoplysninger, Business-plan påkrævet
GET/public-api/v1/design-imports/:id/files/:fileIdDownloader en fil fra en designimportbeskrivelse.godkendte legitimationsoplysninger, Business-plan påkrævet
GET/public-api/v1/file/public/products/:productId/:sizeReturnerer en offentlig produktforhåndsvisning. Størrelsen skal være small.png, medium.png eller big.png.offentlig
GET/public-api/v1/file/protected/:keyReturnerer en beskyttet fil efter lagernøgle.signeret URL eller files:read
GET/public-api/v1/fontsReturnerer alle tilgængelige skrifttyper.offentlig
GET/public-api/v1/currenciesReturnerer alle valutaer.offentlig
POST/public-api/v1/runtime-bindings/sync-from-wordpressOpretter eller opdaterer runtimebindinger fra WordPress-produkttilknytninger.vilkårlige godkendte legitimationsoplysninger
PATCH/public-api/v1/runtime-bindings/:idOpdaterer dele af en runtimebinding.vilkårlige godkendte legitimationsoplysninger
POST/public-api/v1/runtime-bindings/:id/activateAktiverer en runtimebinding.vilkårlige godkendte legitimationsoplysninger
POST/public-api/v1/runtime-bindings/:id/deactivateDeaktiverer en runtimebinding.vilkårlige godkendte legitimationsoplysninger
POST/public-api/v1/wp-connect/exchangeUdveksler en overdragelseskode fra automatisk WordPress-tilslutning med API-legitimationsoplysninger.engangskode til overdragelse
GET/public-api/v1/model-generator/catalogViser synlige generatorprodukter, konfigurationer og skabelonrevisioner.embed:session:create
GET/public-api/v1/model-generator/modelsViser modeller med fastlåste beskrivelser af generatorkilden til import.embed:session:create
GET/public-api/v1/model-generator/designer-catalogReturnerer det generatormodelkatalog, som Designer bruger.embed:session:create
GET/public-api/v1/model-generator/projectsViser ejerens og globalt tilgængelige generatorprojekter.embed:session:create
GET/public-api/v1/model-generator/projects/:projectIdReturnerer den seneste eller valgte projektrevision, skabelonen og filmanifestet.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/revisions/:revisionReturnerer den seneste eller valgte projektrevision, skabelonen og filmanifestet.embed:session:create
GET/public-api/v1/model-generator/projects/:projectId/artifacts/:artifactIdHenter en resultatfil efter at have kontrolleret adgangen til dens projekt.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/templateReturnerer et tilgængeligt skabelondokument for den valgte konfigurationsrevision.embed:session:create
GET/public-api/v1/model-generator/configurations/:configurationId/revisions/:revision/importReturnerer skabelonens importpakke med afhængighedsfiler.embed:session:create
GET/public-api/v1/model-generator/mannequinsReturnerer begge mannequiner og deres ressourcebeskrivelser.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assetsViser ressourcer fra tekstur- eller baggrundsbiblioteket med filer, der kan importeres.embed:session:create
GET/public-api/v1/model-generator/image-libraries/:kind/assets/:assetIdReturnerer en tekstur- eller baggrundsressource med dens importerbare filer.embed:session:create
GET/public-api/v1/model-generator/public-files/:keyHenter en tilladt afhængighedsfil til generatoren.embed:session:create

Kundeordrer

Kundeordreendpoints lader en ekstern butik læse konfigurerede ordrelinjer, opdatere antal, føre en ordre gennem behandlingsstatusser og fjerne opgivne ordrer.

ParameterPåkrævetDetaljer
namenejSøger efter designnavn og numerisk ordre-ID.
category_idnejFiltrerer efter produktkategori-ID.
order_statusnejEn af de tilladte ordrestatusser.
offsetnejStandard 0. Skal være >= 0.
limitnejStandard 9 for denne controller, højst 50.
order_bynejid, created_at eller design_name.
directionnejASC eller DESC.

Eksempel på anmodning (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]
  })
});

Tilladte værdier

StatusBeskrivelse
shopping_cartKurveforløb; kunden kan stadig redigere konfigurationen.
editableOrdren kan fortsat redigeres af kunden.
paidOrdren er betalt og klar til behandling.
processingOrdren er under behandling.
completedOrdren er færdigbehandlet.
cancelledOrdren er annulleret.

Eksempel på anmodning (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'
});

Eksempel på svar

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

Butiksprodukter

Produktendpoints returnerer butiksdesigns, der kan indlejres som Viewer-, Configurator- eller Customizer-oplevelser.

ParameterPåkrævetDetaljer
namenejSøger efter produkt-/designnavn.
customizernejtrue eller false.
offsetnejStandard 0. Skal være >= 0.
limitnejStandard 9, højst 50.
order_bynejid, name eller created_at.
directionnejASC eller DESC.

Eksempel på anmodning (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');

Eksempel på svar

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

Indlejringssessioner og runtimeopstart

Opret et kortlivet indlejringstoken på din server, send det til iframen/runtimet, og lad derefter runtimet kalde bootstrap med et Bearer-token.

ParameterPåkrævetDetaljer
runtimeBindingIdanbefaletForetrukken identifikator for aktive runtimebindinger.
toolpåkrævet uden runtimeBindingIddesigner | viewer | configurator | customizer | model-generator
toolIdtool: model-generatorPositivt numerisk ID for det lokale generatorprojekt, ikke dets UUID eller WooCommerce-produktets ID.
originjaOrigin, hvor indlejringen vises, f.eks. https://yourstore.com.
designIdén identifikatorAlter Product-design-ID. Må ikke kombineres med orderId.
orderIdén identifikatorCustomizer-ordre-ID. Kun gyldigt for customizer.
cartKey + cartModenejKurvekontekst kun til Customizer. cartMode er view eller edit.

Eksempel på anmodning (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 });

Bemærkninger

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

Eksempel på svar

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

Generatorens importendpoints er skrivebeskyttede server-til-server-anmodninger. De kræver de almindelige API-headere, rettighedsomfanget embed:session:create og et aktivt abonnement. Importtilladelsen udsteder ikke en redigeringssession og bruger ikke af dens månedlige kvote. Når editoren åbnes, bruges den samme monthlyEmbedTokenLimit-tæller som til de øvrige indlejrede værktøjer.

Find og importér generatormodeller

Brug /model-generator/models til at vise tilgængelige modeller med generatorer. Beskrivelsen generator fastlåser projectId, revision, configurationId, templateRevision, productId og productModel3dId til bestemte værdier. Følg dens importPath for at hente præcis den pågældende kilderevision. Manifester for produktressourcer indeholder også generators og hver models generator-beskrivelse. Skabeloner kan importeres separat efter konfiguration og revision.

Katalogfiltre

EndpointDetaljer
/model-generator/modelsModelliste: name (eller q), categoryId, scope (all, own, global), limit (1–50) og offset.
/model-generator/catalogSkabelonkatalog: generatorType, productId, audience, q, templateKey, configurationId, limit og offset.
/model-generator/projectsProjektliste: configurationId, q, scope (all, own, global), limit og offset. Den offentlige proxy bruger all som standardværdi for scope.
/model-generator/image-libraries/:kind/assetsTekstur-/baggrundsbiblioteker: kind er texture eller background; q, category og mapType filtrerer de tilgængelige ressourcer.

En projektimport indeholder document, revision, template og et files-manifest. Hver fil angiver en path under /v1/model-generator/; sæt /public-api foran stien, når filen hentes fra Alter Product. Kopiér de nødvendige filer til dit eget lager, og erstat kildereferencer med lokale referencer. Importér mannequiner og teksturbiblioteker via deres katalogendpoints; public-files er begrænset til tilladte ressourcestier, og skabeloner skal bestå adgangskontrollen for deres konfiguration og revision.

Eksempel på anmodning (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 });

Redigeringssession og lokal lagring

Opret redigeringssessionen med tool: model-generator, et positivt numerisk toolId, der identificerer det lokale generatorprojekt (ikke dets UUID eller WooCommerce-produkt-ID), samt den tilladte origin for butikken. Send ikke designId, orderId, runtimeBindingId eller kurvfelter til dette værktøj. Generatorprojektets UUID er en separat identifikator. Send det returnerede token via iframe-håndtrykket; initialiseringen af kørselsmiljøet returnerer generatorkonteksten med 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);

Eksempel på svar

{
  "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-beskeder, som WordPress-broen bruger

WordPress-pluginet stiller lagringsbroen til rådighed og kontrollerer administrator- eller WooCommerce-butiksadministratorrettigheder. Det validerer iframe-vinduets origin, kildevinduet, nonce, anmodnings-ID og tilladte projektstier. Broen sender lokale læsninger og skrivninger til /wp-json/alter-wc/v1/model-generator. API-legitimationsoplysninger bliver på serveren. En tilpasset integration skal implementere tilsvarende godkendt lagringshåndtering; generatorens offentlige API gemmer ikke projekter hos Alter Product.

TypeBeskrivelse
ALTER_CHILD_HELLO / ALTER_PARENT_ACKUndervinduet starter håndtrykket med en nonce; forældrevinduet bekræfter den samme nonce.
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READYUndervinduet anmoder om en redigeringssession til model-generator; forældrevinduet returnerer det autoriserede token.
ALTER_MODEL_GENERATOR_REQUESTUndervinduet sender requestId, nonce og request, der indeholder method, path, data og responseType.
ALTER_MODEL_GENERATOR_RESPONSEForældrevinduet svarer med samme requestId og nonce samt status, data, headers og eventuelle 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.

Ved lagring sendes expectedRevision, templateRevision, document og referencer til resultatfiler. Der oprettes en uforanderlig revision; en forældet expectedRevision returnerer HTTP 409. WordPress gemmer metadata i databasen og filer i mappen uploads. JSON kompakteres og komprimeres med gzip, når komprimeringen reducerer størrelsen.

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

Brug gemt model i design udgiver en fuldstændig gemt revision til et tilknyttet design. Kunderne ser den derefter gennem den eksisterende Customizer, Configurator eller Viewer med de sædvanlige produkttilknytninger og abonnementskontroller. Generatoreditoren forbliver et værktøj til forhandleren. Ordretilknytninger bevarer det gemte projekt og dets revision, så senere redigeringer ikke ændrer tidligere ordrer ubemærket.

Ressourcekatalog

Ressourcekataloget giver adgang til produkters kilderessourcer, baggrunde, miljøer, grafikbiblioteksobjekter, designskabeloner og mockupressourcer. Listeendpoints returnerer kompakte beskrivelser; detaljeendpoints indeholder filmanifester.

TypeBeskrivelse
productsBasisproduktressourcer, forhåndsvisninger, 3D-modeller samt materiale- og teksturbeskrivelser.
backgroundsStatiske Viewer-baggrunde.
environmentsMiljøkort og forhåndsvisningsbilleder.
image_libraryGrafikbiblioteksressourcer, herunder butiksspecifik grafik.
design_templatesForhåndsvisninger af designskabeloner og referencer til lagfiler. Understøtter product_id-filter.
mockupsMockupgeneratorens ressourcer, baggrunde og overlejringskort. Understøtter product_id-filter.

Eksempel på anmodning (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();

Eksempel på svar

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

Designimport

Designimport giver adgang til designs og filer, der er hostet hos Alter, til ekstern produktion eller migrering. API'et kontrollerer adgangen til Business-planen.

ParameterPåkrævetDetaljer
searchnejSøger efter designtitel eller ID.
offsetnejStandard 0.
limitnejStandard 20, højst 100.

Eksempel på anmodning (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();

Eksempel på svar

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

Filer, skrifttyper og valutaer

Offentlige forhåndsvisningsfiler kan bruges i browsere. Beskyttede filer kræver en signeret URL eller API-legitimationsoplysninger med files:read. Skrifttyper og valutaer har offentlige læseendpoints.

EndpointAdgangDetaljer
/file/public/products/:productId/small.pngoffentligLille produktforhåndsvisning.
/file/public/products/:productId/medium.pngoffentligMellemstor produktforhåndsvisning.
/file/public/products/:productId/big.pngoffentligStor produktforhåndsvisning.
/file/protected/:keysigneret URL eller files:readBeskyttet fil i objektlager.
/fontsoffentligArray med skrifttypeposter.
/currenciesoffentligArray med valutaposter.

Eksempel på anmodning (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());

Eksempel på svar

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

Runtimebindinger

Runtimebindinger forbinder eksterne e-handelsprodukter med Alter Product-designs og runtimetyper. De bruges primært af WordPress/WooCommerce-integrationer og avancerede butiksbackends.

ParameterPåkrævetDetaljer
designIdnejAlter Product-design-ID, der tilhører butikken.
externalProductIdja til synkroniseringEksternt produkt-ID, f.eks. et WooCommerce-produkt-ID.
runtimeTypeja til synkroniseringviewer, configurator eller customizer.
statusnejdraft, active, inactive, archived eller legacy_active.
legacyStorefrontProductIdnejValgfrit ældre tilknytnings-ID.
legacyBindingMetanejValgfrie JSON-metadata, f.eks. manifestHash.

Eksempel på anmodning (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'
          }
        }
      }
    ]
  })
});

Eksempel på svar

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

WordPress-forbindelsesudveksling

Endpointet til WordPress-forbindelsesudveksling bruger en engangskode og returnerer API-legitimationsoplysninger til pluginet. Det er ikke et generelt endpoint til oprettelse af legitimationsoplysninger.

Eksempel på anmodning (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();

Eksempel på svar

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

Fejl og anmodningsgrænser

De fleste controllerfejl normaliseres til et svar med code. Godkendelsesmiddleware og anmodningsbegrænsere kan i stedet returnere et svar med error.

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

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

{
  "error": "Too Many Requests"
}
TypeGrænseTidsvindue
Globalt600 anmodninger60 sekunder
GET /auth/check60 anmodninger60 sekunder
Læsning af ordrer/produkter300 anmodninger60 sekunder
Skrivning af ordrer/indlejringssessioner/runtimebindinger120 anmodninger60 sekunder
Læsning af ressourcer/designimport180 anmodninger60 sekunder
Skrifttyper300 anmodninger60 sekunder
WP-forbindelsesudveksling30 anmodninger60 sekunder
GET /model-generator/*600 anmodninger60 sekunder