Integrazioni E-commerce 12 min di lettura 15 febbraio 2026

Integrare i marketplace: Shopify, Amazon, TikTok Shop e le API di unified commerce

Un'analisi tecnica approfondita dell'integrazione unified commerce: come sincronizzare inventario, ordini e catalogo prodotti su Shopify, Amazon SP-API e TikTok Shop senza costruire un'integrazione fragile e ingestibile.

LD

Luigi De Rosa

Senior Backend Engineer

Il retail multicanale è la norma per qualsiasi brand e-commerce con scala significativa. Un brand vende sul proprio negozio Shopify, su Amazon, su TikTok Shop e — sempre più spesso — su marketplace regionali come Allegro o Cdiscount. Ogni canale ha la propria API, il proprio modello di dati, i propri rate limit e i propri failure mode. Senza un'architettura di integrazione coerente, il risultato è una rete fragile di webhook, esportazioni manuali e discrepanze di inventario che consumano banda operativa e danneggiano l'esperienza cliente.

Questo articolo descrive l'architettura che abbiamo costruito per clienti che gestiscono tre o più canali marketplace, i pattern API che ciascuna piattaforma utilizza e i principi di sincronizzazione dei dati che prevengono i fallimenti di integrazione più comuni.

Il problema centrale: N modelli API, 1 modello di business

Ogni marketplace ha un modello di dati internamente coerente ma esternamente incompatibile. Shopify ha varianti e opzioni; Amazon ha ASIN e SKU in una gerarchia genitore-figlio; TikTok Shop ha SPU e SKU con una struttura di attributi di prodotto differente. Un ordine su Shopify ha line item; un ordine Amazon ha order item con riferimenti ASIN; gli ordini TikTok hanno order line con tracking delle promozioni. Mappare tra questi modelli senza una rappresentazione interna canonica crea un incubo di manutenzione man mano che ciascuna piattaforma evolve.

Architettura di integrazione

Channel AdapterConnettori per piattaforma che traducono i modelli API esterni in eventi interni canonici
Modello dati canonicoRappresentazione interna di prodotti, inventario, ordini — indipendente dalla piattaforma
Event BusRabbitMQ/Kafka pubblica eventi canonici a tutti i consumer interessati
Sync EngineDetermina cosa spingere su ciascun canale e gestisce la risoluzione dei conflitti
Audit LogLog immutabile di ogni operazione di sincronizzazione per debug e riconciliazione

Integrazione Shopify

Le API REST e GraphQL Admin di Shopify sono tra le più mature nell'e-commerce. Per le nuove integrazioni usiamo l'API GraphQL — offre operazioni batch, selezione precisa dei campi ed è dove Shopify sta investendo le nuove funzionalità.

Sincronizzazione inventario tramite GraphQL

shopify-inventory-sync.tstypescript
const MUTATION_AGGIORNA_INVENTARIO = gql`
  mutation inventorySetOnHandQuantities($input: InventorySetOnHandQuantitiesInput!) {
    inventorySetOnHandQuantities(input: $input) {
      userErrors { field message }
      inventoryAdjustmentGroup {
        changes {
          item { inventoryItemId }
          delta
          quantityAfterChange
        }
      }
    }
  }
`;

async function sincronizzaInventarioShopify(
  articoli: { shopifyInventoryItemId: string; locationId: string; quantita: number }[]
): Promise<void> {
  // Shopify permette fino a 250 articoli per mutation
  const batch = chunk(articoli, 250);

  for (const gruppo of batch) {
    const { data } = await shopifyClient.mutate({
      mutation: MUTATION_AGGIORNA_INVENTARIO,
      variables: {
        input: {
          reason: "correction",
          setQuantities: gruppo.map((articolo) => ({
            inventoryItemId: articolo.shopifyInventoryItemId,
            locationId: articolo.locationId,
            quantity: articolo.quantita,
          })),
        },
      },
    });

    if (data.inventorySetOnHandQuantities.userErrors.length > 0) {
      throw new ShopifyInventorySyncError(data.inventorySetOnHandQuantities.userErrors);
    }
  }
}

Gestione affidabile dei webhook Shopify

I webhook di Shopify non garantiscono la consegna esattamente una volta. Possono essere consegnati più volte (retry in caso di errore HTTP) e possono arrivare fuori ordine. Il tuo gestore di webhook deve essere idempotente e dovrebbe controllare i timestamp degli eventi prima di aggiornare lo stato.

shopify-webhook-handler.tstypescript
@Post("webhooks/shopify")
async gestisciWebhookShopify(
  @Headers("x-shopify-topic") topic: string,
  @Headers("x-shopify-hmac-sha256") firma: string,
  @RawBody() rawBody: Buffer,
  @Body() payload: unknown,
): Promise<void> {
  // 1. Verifica la firma HMAC
  const firmaAttesa = createHmac("sha256", process.env.SHOPIFY_WEBHOOK_SECRET)
    .update(rawBody)
    .digest("base64");

  if (!timingSafeEqual(Buffer.from(firma, "base64"), Buffer.from(firmaAttesa, "base64"))) {
    throw new UnauthorizedException("Firma webhook non valida");
  }

  // 2. Accoda per elaborazione asincrona — restituisce 200 velocemente per evitare retry Shopify
  await this.webhookQueue.add(topic, { topic, payload }, {
    attempts: 3,
    backoff: { type: "exponential", delay: 5000 },
    removeOnComplete: 1000,
  });
}

Integrazione Amazon SP-API

L'Amazon Selling Partner API (SP-API) è il successore di MWS e opera su OAuth 2.0 con token LWA (Login with Amazon). È potente ma ha rate limit rigidi (il throttling è per operazione, per marketplace) e richiede una gestione attenta del backoff.

Client API con rate limiting

amazon-sp-api-client.tstypescript
class AmazonSPAPIClient {
  private readonly rateLimiter: RateLimiter;
  private accessToken: string | null = null;
  private scadenzaToken: Date | null = null;

  constructor(private readonly credenziali: SPAPICredenziali) {
    // Rate limiter per operazione basati sulle quote pubblicate da Amazon
    this.rateLimiter = new RateLimiter({
      "getOrders": { tokensPerSecond: 0.0167 }, // 1 richiesta al minuto
      "getInventorySummaries": { tokensPerSecond: 2 },
      "updateListingsItem": { tokensPerSecond: 5 },
    });
  }

  async richiesta<T>(operazione: string, params: Record<string, unknown>): Promise<T> {
    await this.rateLimiter.consuma(operazione);

    const token = await this.getAccessToken();

    try {
      const risposta = await fetch(`${SPAPI_BASE_URL}/${operazione}`, {
        headers: {
          "x-amz-access-token": token,
          "Content-Type": "application/json",
        },
        ...params,
      });

      if (risposta.status === 429) {
        const retryAfter = parseInt(risposta.headers.get("retry-after") ?? "60");
        await attendi(retryAfter * 1000);
        return this.richiesta(operazione, params); // retry una volta
      }

      return risposta.json() as T;
    } catch (errore) {
      throw new SPAPIError(operazione, errore);
    }
  }
}

Elaborazione del feed ordini

Amazon non invia webhook per gli ordini — è necessario interrogare il polling sull'endpoint getOrders. Eseguiamo un job pianificato ogni 5 minuti che recupera gli ordini in stato PendingAvailability, Pending, Unshipped dall'ultimo timestamp di polling riuscito. Questo timestamp viene memorizzato in modo persistente e avanzato solo dopo l'elaborazione riuscita di tutti gli ordini recuperati.

Integrazione TikTok Shop

TikTok Shop è il canale principale più recente e la sua API è ancora in maturazione. L'architettura è simile a Shopify (REST-ish, webhook-driven) ma il modello prodotto differisce significativamente — TikTok usa il concetto di SPU (Standard Product Unit) a livello di listing e SKU a livello di variante, con attributi di compliance obbligatori che variano per categoria.

La problematica più critica specifica di TikTok è l'integrazione del live commerce. Quando un prodotto è in primo piano in una diretta LIVE, l'inventario può passare da 1.000 a zero in sessanta secondi. La sincronizzazione dell'inventario deve dare priorità agli eventi di prenotazione di TikTok Shop con latenza quasi in tempo reale, altrimenti si verificherà l'overselling. Risolviamo questo con un consumer di eventi TikTok dedicato che aggira la coda di sincronizzazione standard e blocca direttamente l'inventario nel canonical store.

Sincronizzazione inventario: la parte difficile

La sincronizzazione dell'inventario è la parte tecnicamente più impegnativa dell'integrazione multicanale. La sfida fondamentale è che più canali possono consumare simultaneamente lo stesso inventario fisico. Senza un sistema di prenotazioni, l'overselling è inevitabile.

inventory-reservation.service.tstypescript
@Injectable()
export class InventarioPrenotazioneService {
  // Prenotazione atomica usando Redis per prevenire race condition
  async prenotaInventario(
    sku: string,
    quantita: number,
    canale: Canale,
    idOrdine: string,
  ): Promise<boolean> {
    const chiave = `inventario:${sku}`;
    const chiavePrenotazione = `prenotazione:${idOrdine}`;

    // Script Lua garantisce l'atomicità — legge e scrive in un'unica operazione
    const luaScript = `
      local corrente = tonumber(redis.call('GET', KEYS[1]) or '0')
      if corrente < tonumber(ARGV[1]) then
        return 0  -- scorte insufficienti
      end
      redis.call('DECRBY', KEYS[1], ARGV[1])
      redis.call('SETEX', KEYS[2], 3600, ARGV[2])  -- prenotazione scade in 1h
      return 1  -- successo
    `;

    const risultato = await redis.eval(
      luaScript,
      2,
      chiave,
      chiavePrenotazione,
      quantita.toString(),
      JSON.stringify({ sku, quantita, canale, idOrdine }),
    );

    return risultato === 1;
  }
}

Sincronizzazione del catalogo prodotti

Mantenere un catalogo prodotti canonico e distribuirlo su più canali è complesso perché ogni canale richiede dati diversi: Amazon ha bisogno di bullet point, search term e browse node ID; Shopify ha bisogno di metafield e assegnazioni alle collezioni; TikTok ha bisogno di certificati di compliance e attributi specifici per categoria. Modelliamo questo come un prodotto canonico con override per canale, memorizzati come JSONB in PostgreSQL.

Gestione degli errori e riconciliazione

  • Tutte le operazioni di sincronizzazione scrivono in un audit log immutabile con input, output, timestamp e identificatore del canale.
  • Le operazioni di sincronizzazione fallite vengono ritentate con backoff esponenziale e spostate in una coda dead-letter dopo N tentativi.
  • Un job di riconciliazione giornaliero confronta i livelli di inventario canonici con i livelli riportati da ciascuna API marketplace e segnala le discrepanze.
  • Alert inviati ai team operativi quando la discrepanza di inventario supera il 5% per qualsiasi SKU.
  • Ogni risposta API del marketplace include correlation ID memorizzati insieme alla voce dell'audit log per il debugging.

Conclusioni

L'integrazione unified commerce non è mai solo un esercizio di integrazione API — è un problema di consistenza dei dati su larga scala. I team che lo fanno bene investono in un modello di dati canonico fin dal primo giorno, trattano la prenotazione dell'inventario come un sistema critico in tempo reale e costruiscono audit e riconciliazione nell'architettura prima di scrivere la prima funzione di sincronizzazione. I team che lo fanno male finiscono con una patchwork di chiamate API dirette, fogli di correzione manuali e un team di assistenza clienti sopraffatto da dispute per overselling.

Nexora ha costruito integrazioni unified commerce che collegano Shopify, Amazon SP-API, TikTok Shop, Miravia ed ERP interni per clienti retail. Se stai costruendo o scalando un'operazione commerce multicanale, possiamo progettare e implementare il layer di integrazione.

Tag

ShopifyAmazonTikTok ShopE-commerceAPIIntegrazioneUnified Commerce

Prossimo passo

Hai bisogno di implementare questa architettura?

Il nostro team di ingegneria costruisce e scala i sistemi descritti in questo articolo. Dalla discovery alla produzione — con risultati misurabili.