Vai al contenuto
Menu documenti

API REST

Prodotti

Elenco, ricerca, lettura e creazione o aggiornamento di prodotti, con prezzi di lista o qualsiasi prezzo del cliente.

Un prodotto ha un SKU, un prezzo di listino e un marchio, una categoria, uno stato di magazzino e dettagli aggiuntivi opzionali. I prezzi vengono sempre calcolati per voi: consulta Prezzi.

I prodotti possono anche avere familyId e orderStep (valore predefinito 1). Una lettura di un singolo prodotto include metadati opzionali family con il suo nome, i nomi degli attributi delle varianti e i valori predefiniti. Un prezzo configurato contiene orderingFields, configurationRequired, definitionVersion e un prezzo clienti opzionale quantityBreaks. I campi di ordinamento sono input dell'acquirente; details rimangono fatti del prodotto.

POST/api/v1/products/{id}/quote

Questa operazione in sola lettura accetta { "customer": "ACME01", "qty": 3, "configuration": { "length": 2.75, "reference": "Kitchen" } }. customer è opzionale per il listino prezzi del personale. Le chiavi in sola lettura possono utilizzarla. Restituisce data.productId, qty, fields validati, definitionVersion e price con unit, line e la specifica scelta. I campi obbligatori mancanti restituiscono Configura per il prezzo; le combinazioni non valide vengono rifiutate. Non crea un carrello, un ordine o un pagamento. Usa price.line invece di moltiplicare il prezzo unitario.

Gli import accettano family, orderStep e orderingDefinition opzionali. Una definizione utilizza lo schema in OpenAPI, richiede il piano Pro e il permesso per i prezzi globali, e restituisce ruleDrafts per la revisione attraverso il flusso di lavoro esistente per modifiche al prezzo. La struttura omessa lascia invariati i settaggi esistenti. Vedi setup del catalogo commerciale.

L'oggetto prodottoCollegamento a questa sezione#

json
{
  "id": "3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c",
  "sku": "HX-8510",
  "name": "Hex bolt M10 x 50 zinc",
  "description": "Grade 8.8, zinc plated, fully threaded.",
  "brandId": "a1b2c3d4-0000-4000-8000-000000000001",
  "categoryId": "a1b2c3d4-0000-4000-8000-000000000002",
  "manufacturerRef": "DIN933-M10-50",
  "unitLabel": "Box of 100",
  "minOrderQty": 1,
  "availability": "in_stock",
  "stockQty": 240,
  "lowStockAt": null,
  "leadTimeNote": null,
  "dealText": null,
  "active": true,
  "visibility": "all",
  "details": { "Finish": "Zinc", "Thread": "M10" },
  "createdAt": "2026-08-14T09:30:00.000Z",
  "updatedAt": "2026-09-20T16:02:11.000Z",
  "price": {
    "unit": 1850,
    "line": 1850,
    "list": 1850,
    "discountBp": 0,
    "source": "list",
    "label": ""
  }
}
CampoTipoDescrizione
idstringaID del prodotto.
skustringaIl tuo codice di magazzino. Unico nello spazio di lavoro, ignorando la maiuscola/minuscola.
namestringNome del prodotto.
descriptionstring o nullDescrizione più lunga.
brandId, categoryIdstring o nullVedi brand e categorie.
manufacturerRefstring o nullNumero di pezzo del produttore. Cercabile come lo SKU.
unitLabelstringCosa rappresenta una singola unità, ad esempio "Ogni" o "Scatola da 100".
minOrderQtyinteroQuantità minima che i clienti possono ordinare.
availabilitystringnot_tracked, in_stock, low_stock, out_of_stock o made_to_order. Un'etichetta solo per i compratori: ogni prodotto può essere ordinato. Inviandolo senza un stockQty si cancella il conteggio memorizzato (stai impostando lo stato manualmente). Con un stockQty viene calcolato per te: 0 o meno è out_of_stock, fino al livello minimo è low_stock, sopra di esso è in_stock. made_to_order non viene mai modificato dal numero.
stockQtyinteger o nullUnità disponibili, o null quando non conti questo prodotto. Quando impostato, availability lo segue. Escluso quando lo chiedi come cliente (customer).
lowStockAtinteger o nullLivello di scorta minimo del prodotto, o null per utilizzare il livello dell'ambiente di lavoro. Escluso quando lo chiedi come cliente.
leadTimeNotestring o nullAd esempio "3-5 giorni lavorativi".
dealTextstring o nullUn nota visualizzata accanto al prezzo, ad esempio "min 12 btls 45". La sua intestazione è l'etichetta di offerta del workspace (Impostazioni, Visualizzazione catalogo).
activebooleanI prodotti non attivi sono nascosti ai clienti.
visibilitystringall, o selected quando solo i clienti selezionati possono vederlo.
detailsobjectColonne aggiuntive dagli import, come { "Finish": "Zinc" }.
priceobject o nullIl prezzo alla quantità 1 (o qty). Vedere Prezzi. unit è null quando il prodotto non ha ancora un prezzo.

I conteggi di magazzino sono tuoi da tenere aggiornati: gli ordini non cambiano mai stockQty, quindi invialo dal tuo sistema di magazzino ogni volta che cambia. I clienti vedono solo lo stato availability, mai il numero. A zero un prodotto può ancora essere ordinato; è semplicemente contrassegnato come esaurito.

GET /products/{id} include anche i nomi brand e category.

Le immagini non vengono restituite dall'API. Puoi impostarne una con imageUrl quando crei o aggiorni.

Elenco o ricerca prodottiCollegamento a questa sezione#

GET/api/v1/products

Senza q, i prodotti vengono elencati per nome. Con q, i risultati vengono restituiti in questo ordine:

  1. SKU esatto o riferimento del produttore
  2. SKU o riferimento del produttore che inizia con q
  3. corrispondenze complete del testo sul nome, marca, categoria e descrizione (3 o più caratteri; le query più brevi corrispondono all'inizio del nome)

Passa customer per applicare il prezzo a ogni riga per quel cliente e restituire solo i prodotti che quel cliente può visualizzare (attivi e che sono per tutti o selezionati per loro). È esattamente ciò che il cliente vede nel loro portale di commercio.

NomeTipoObbligatorioDescrizione
qstringanoSKU, riferimento del produttore, nome, marchio o categoria. Fino a 200 caratteri.
categorystringanoID della categoria.
brandstringanoID del marchio.
availabilitystringanoUno dei valori di disponibilità.
activetrue o falsenotrue restituisce solo i prodotti attivi. Il valore predefinito è true quando customer è impostato; altrimenti vengono restituiti tutti i prodotti.
customerstringanoID del cliente o codice account.
limitinteronoDa 1 a 50. Predefinito 50.
offsetinteronoRighe da saltare. Predefinito 0.
bash
curl "https://tradecatalog.app/api/v1/products?q=hex%20bolt&customer=OAK01&limit=20" \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
js
const params = new URLSearchParams({
  q: 'hex bolt',
  customer: 'OAK01',
  limit: '20',
})
const res = await fetch(`https://tradecatalog.app/api/v1/products?${params}`, {
  headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: products, nextOffset } = await res.json()
json
{
  "data": [
    {
      "id": "3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c",
      "sku": "HX-8510",
      "name": "Hex bolt M10 x 50 zinc",
      "description": "Grade 8.8, zinc plated, fully threaded.",
      "brandId": "a1b2c3d4-0000-4000-8000-000000000001",
      "categoryId": "a1b2c3d4-0000-4000-8000-000000000002",
      "manufacturerRef": "DIN933-M10-50",
      "unitLabel": "Box of 100",
      "minOrderQty": 1,
      "availability": "in_stock",
      "leadTimeNote": null,
      "active": true,
      "visibility": "all",
      "details": { "Finish": "Zinc", "Thread": "M10" },
      "createdAt": "2026-08-14T09:30:00.000Z",
      "updatedAt": "2026-09-20T16:02:11.000Z",
      "price": {
        "unit": 1573,
        "line": 1573,
        "list": 1850,
        "discountBp": 1500,
        "source": "brand",
        "label": "Brand discount −15%"
      }
    }
  ],
  "nextOffset": null,
  "currency": "GBP"
}

Ottieni un prodottoCollegamento a questa sezione#

GET/api/v1/products/{id}

NomeInTipoObbligatorioDescrizione
idpathstringasìID del prodotto.
customerquerystringanoID del cliente o codice account. Restituisce 404 se il cliente non può visualizzare il prodotto.
qtyqueryinteronoQuantità da prezzare, da 1 a 1.000.000. Predefinito 1. price.line è unit × qty.
bash
curl "https://tradecatalog.app/api/v1/products/3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c?customer=OAK01&qty=5" \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
js
const res = await fetch(
  `https://tradecatalog.app/api/v1/products/${productId}?customer=OAK01&qty=5`,
  { headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` } },
)
const { data: product } = await res.json()
json
{
  "data": {
    "id": "3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c",
    "sku": "HX-8510",
    "name": "Hex bolt M10 x 50 zinc",
    "description": "Grade 8.8, zinc plated, fully threaded.",
    "brandId": "a1b2c3d4-0000-4000-8000-000000000001",
    "categoryId": "a1b2c3d4-0000-4000-8000-000000000002",
    "manufacturerRef": "DIN933-M10-50",
    "unitLabel": "Box of 100",
    "minOrderQty": 1,
    "availability": "in_stock",
    "leadTimeNote": null,
    "active": true,
    "visibility": "all",
    "details": { "Finish": "Zinc", "Thread": "M10" },
    "createdAt": "2026-08-14T09:30:00.000Z",
    "updatedAt": "2026-09-20T16:02:11.000Z",
    "brand": "Northgate",
    "category": "Bolts",
    "price": {
      "unit": 1573,
      "line": 7865,
      "list": 1850,
      "discountBp": 1500,
      "source": "brand",
      "label": "Brand discount −15%"
    }
  },
  "currency": "GBP"
}

Per cercare un prodotto per SKU, utilizzare GET /products?q=HX-8510: un match esatto dello SKU è sempre prioritario. Oppure utilizzare GET /prices, che accetta un SKU.

Crea o aggiorna prodottiCollegamento a questa sezione#

PUT/api/v1/productschiave di scrittura

Invia fino a 100 prodotti per chiamata. Ogni prodotto viene abbinato a un prodotto esistente tramite SKU, ignorando il caso. Se non c'è corrispondenza, viene creato un nuovo prodotto. Marche e categorie vengono abbinati per nome e creati se non esistono.

Come vengono gestiti i prezzi di listinoCollegamento a questa sezione#

Il prodotto...Cosa succede al prezzo
è nuovoVa in vendita a listPrice immediatamente.
esiste ma non ha ancora un prezzoVa in vendita a listPrice immediatamente.
esiste allo stesso prezzoNiente.
esiste a un prezzo diversoNiente cambia ancora. Il nuovo prezzo va in un cambiamento di prezzo in bozza per quella lista. priceChangeId è la bozza per la lista di listPrice. priceChangesByList ha un'entrata per ogni lista che è cambiata.

I cambiamenti di prezzo in bozza sono il modo in cui TradeCatalog evita che un errore di battitura raggiunga i clienti. Il proprietario o il personale recensisce la bozza nell'app (Cambiamenti prezzo), controlla i movimenti più importanti e gli avvisi, sceglie una data e se inviare una e-mail ai clienti, quindi pubblica. È possibile visualizzare in anteprima una bozza con GET /price-changes/{id}.

Una sincronizzazione, un bozzo per lista

Una chiamata che modifica i prezzi inizia una bozza per lista, chiamata "Importazione API (nome chiave)" per Standard e con il nome della lista quando invii più di una. Per mantenere una sincronizzazione intera in quelle bozze, invia priceChangeId (la lista per listPrice) e drafts (le altre liste) dalla prima chiamata con ogni chiamata successiva. Ogni lista deve ancora essere una bozza: una volta pubblicata, annullata o eliminata, lascia fuori quell'id per iniziare una nuova bozza.

CorpoCollegamento a questa sezione#

CampoTipoObbligatorioDescrizione
productsarraysì1 a 100 prodotti. I codici SKU devono essere unici all'interno della chiamata.
priceChangeIdstringnoUna bozza per l'elenco listPrice da una chiamata precedente. I prezzi modificati per quell'elenco vengono aggiunti ad essa. 404 se non esiste, 400 se non è più una bozza.
draftsarraynoFino a 30 voci { list, priceChangeId } in modo che altri elenchi possano continuare le proprie bozze.
products[].skustringsìFino a 64 caratteri.
products[].namestringsìFino a 200 caratteri.
products[].listPriceintero o nullsìUnità minori, da 0 a 1.000.000.000. null è prezzo su richiesta: un prodotto nuovo non ha prezzo, un prodotto esistente mantiene il proprio.
products[].priceListstring o nullnoNome di un elenco prezzi esistente per listPrice. Omettere o null è Standard. Un nome non noto viene rifiutato.
products[].listPricesarraynoAltre liste, come { list, price }. price è unità minori, o null per lasciare quella lista invariata. Un nome sconosciuto viene rifiutato.
products[].unitLabelstringasìFino a 60 caratteri, ad esempio “Ogni”.
products[].brandstringnoNome del marchio, fino a 120 caratteri. Pulito se omesso.
products[].categorystringnoNome della categoria, fino a 120 caratteri. Cancellato se omesso.
products[].manufacturerRefstringnoFino a 120 caratteri. Cancellato se omesso.
products[].descriptionstringnoFino a 4.000 caratteri. Cancellato se omesso.
products[].availabilitystringnoUno dei valori di disponibilità. Conservato se omesso; i nuovi prodotti iniziano come not_tracked.
products[].stockQtyintero o nullnoUnità in magazzino, da -1.000.000 a 1.000.000.000. Imposta availability (vedi l'oggetto prodotto); uno stato che invii insieme a esso viene ignorato, tranne made_to_order. Mantenuto se omesso, a meno che non invii un availability senza di esso: in tal caso, il conteggio viene cancellato e viene utilizzato quel stato. null smette di contare; il availability inviato nella stessa riga si applica, o lo stato corrente se non ce n'è uno.
products[].lowStockAtintero o nullnoLivello di scorta bassa per questo prodotto, da 0. null utilizza il livello del workspace (Impostazioni, 5 per iniziare). Mantenuto se omesso.
products[].leadTimeNotestringnoFino a 200 caratteri. Conservato se omesso.
products[].dealTextstringnoFino a 200 caratteri, visualizzati accanto al prezzo. Conservato se omesso.
products[].detailsoggettonoFino a 30 colonne aggiuntive: nomi fino a 60 caratteri, valori fino a 500. Sostituisce tutti i dettagli quando inviato; mantenuto se omesso.
products[].imageUrlstringanoUn URL di immagine https. Copiato in TradeCatalog in background quando cambia. Mantenuto se omesso.
products[].onlyForarraynoFino a 200 codici account o e-mail di contatto. Rende visibile il prodotto solo per quei clienti, sostituendo qualsiasi elenco precedente. Mantenuto se omesso.

Invia ogni campo che ti interessa

brand, category, manufacturerRef e description vengono scritti come inviati, quindi lasciarne uno fuori li cancella. Invia sempre il prodotto completo, come una riga di un foglio di calcolo.

Queste operazioni non possono essere eseguite tramite l'API per il momento: rendere un prodotto non attivo, minOrderQty, rimuovere un'immagine, cancellare un'appunto sul tempo di attesa e rendere nuovamente visibile a tutti un prodotto riservato ai clienti. Esegui queste operazioni nell'app.

bash
curl -X PUT https://tradecatalog.app/api/v1/products \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      {
        "sku": "HX-8510",
        "name": "Hex bolt M10 x 50 zinc",
        "listPrice": 1950,
        "unitLabel": "Box of 100",
        "brand": "Northgate",
        "category": "Bolts",
        "manufacturerRef": "DIN933-M10-50",
        "availability": "in_stock",
        "details": { "Finish": "Zinc", "Thread": "M10" }
      },
      {
        "sku": "OAK-HNG-75",
        "name": "Oak-finish butt hinge 75mm",
        "listPrice": 695,
        "unitLabel": "Pair",
        "category": "Hinges",
        "onlyFor": ["OAK01"]
      }
    ]
  }'
js
const res = await fetch('https://tradecatalog.app/api/v1/products', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ products }),
})
const { data: result } = await res.json()
if (result.priceChangeId)
  console.log('Review the draft price change in TradeCatalog')
json
{
  "data": {
    "created": 1,
    "updated": 1,
    "priceChanges": 1,
    "priceChangeId": "c4d5e6f7-1234-4abc-9def-0123456789ab",
    "priceChangesByList": [
      {
        "list": "Standard",
        "priceChangeId": "c4d5e6f7-1234-4abc-9def-0123456789ab"
      }
    ],
    "unknownCustomers": []
  }
}
CampoDescrizione
createdNuovi prodotti.
updatedProdotti esistenti corrispondenti al SKU.
priceChangesQuanti prezzi sono entrati in un bozza, su ogni elenco nella chiamata.
priceChangeIdLa bozza per l'elenco listPrice, o null se quell'elenco non aveva modifiche.
priceChangesByListUn { list, priceChangeId } per ogni elenco che ha avuto un cambiamento di prezzo in questa chiamata.
unknownCustomersValori in onlyFor che non hanno corrisposto a nessun cliente (fino a 50). A quei clienti non è stato dato l'accesso.

I cambiamenti appaiono nel registro delle attività con il nome della chiave, e le ricerche vengono aggiornate immediatamente.

Marche e categorieCollegamento a questa sezione#

GET/api/v1/brands

GET/api/v1/categories

Entrambi restituiscono ogni riga, ordinata per nome, senza paginazione. Utilizza gli id con i filtri brand e category su GET /products.

bash
curl https://tradecatalog.app/api/v1/categories \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
js
const res = await fetch('https://tradecatalog.app/api/v1/categories', {
  headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: categories } = await res.json()
json
{
  "data": [
    { "id": "a1b2c3d4-0000-4000-8000-000000000002", "name": "Bolts" },
    { "id": "a1b2c3d4-0000-4000-8000-000000000003", "name": "Hinges" }
  ]
}

Per creare un marchio o una categoria, assegnane un nome a un prodotto in PUT /products.