Cum să îți încarci catalogul pentru SiteChat
Dacă folosești SiteChat pe propriul tău website (nu un magazin Shopify), poți trimite înregistrări structurate de produse către Shoply, astfel încât cumpărătorii să le poată găsi în chatul SiteChat și în căutarea de produse.
Aceste endpointuri folosesc același Settings → Store owner API secret ca restul API-ului Shoply Merchant, iar pagina Product Catalog din adminul SiteChat le poate apela cu tokenul tău de acces admin atunci când ești autentificat. Magazinele Shopify continuă să sincronizeze datele catalogului prin Shopify; aceste rute de încărcare sunt disponibile doar pentru conturile SiteChat care nu sincronizează deja un catalog Magento.
În adminul SiteChat, Product Catalog deschide o zonă în stil Shopify cu Products, Collections și Inventory. Poți adăuga sau edita produse, importa CSV/Excel, grupa produse în colecții manuale și ajusta cantitățile din stoc.
Ce API-uri sunt disponibile?
| API | Metodă | Ce face |
|---|---|---|
/merchant/products/batch | POST | Creează sau înlocuiește complet până la 50 de produse într-o singură cerere |
/merchant/products | POST | Creează sau înlocuiește complet un produs |
/merchant/products | GET | Citește un produs importat după source și external_id |
/merchant/products | PATCH | Actualizează parțial un produs; înlocuirea variantelor sau a metafield-urilor necesită versiunea din GET |
/merchant/products | DELETE | Arhivează logic un produs (status=archived) |
/merchant/products/list | GET | Parcurge paginat produsele importate pentru tabelele din admin |
/merchant/products/images | POST | Încarcă o imagine de produs și primește un URL public HTTPS |
/merchant/collections | GET / POST | Listează sau creează colecții manuale |
/merchant/collections/{id} | GET / PUT / DELETE | Citește, înlocuiește sau arhivează o colecție |
/merchant/inventory | GET | Listează rândurile de stoc (cantități pentru produse și variante) |
/merchant/inventory/adjust | POST | Setează cantitatea urmărită pentru un produs sau o variantă |
Salvările reușite de produse cer Shoply să reconstruiască indexul magazinului. Până când reconstrucția se finalizează, răspunsurile raportează index_status: "pending". Produsele publicate apar apoi atât în indexul de produse, cât și în baza de cunoștințe folosită de chatul SiteChat.
Cine poate folosi aceste API-uri?
- Magazinul tău trebuie să fie un cont SiteChat (
app_platformeste SiteChat). - Cheile magazinelor Shopify (inclusiv orice domeniu
*.myshopify.com) sunt respinse. - Autentificarea trebuie să folosească fie un secret API valid de proprietar al magazinului, fie un token de acces admin SiteChat pentru exact
store_keydin cerere. - Tokenurile Shopify Admin API nu pot apela aceste rute.
Creează sau rotește secretul proprietarului în același mod ca pentru alte integrări Merchant API: Cum să folosești Shoply Merchant API. În consola de administrare SiteChat, deschide Product Catalog pentru a gestiona produse, colecții și inventar — sau pentru a importa un fișier CSV ori Excel — fără să gestionezi tu însuți secretul.
Cum funcționează autentificarea?
Dintr-un conector server
Apelează API-ul dintr-un backend de încredere prin HTTPS. Pune un șir JSON în headerul Authorization:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"store_owner_api_secrete": "YOUR_STORE_OWNER_API_SECRET"
}store_owner_api_secrete este numele public al câmpului, inclusiv ortografia istorică. store_owner_api_secret este de asemenea acceptat. Acesta nu este un token Bearer.
Din adminul SiteChat
Pagina Product Catalog trimite în schimb sesiunea ta de admin autentificată:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN"
}access_token este acceptat ca alias pentru admin_auth_token.
Parametrul de interogare store_key trebuie să corespundă cu headerul. Păstrează secretele proprietarului doar în variabile de mediu de pe server — niciodată într-un script de storefront, într-un URL sau într-un repository public.
export SHOPLY_STORE_KEY="your-sitechat-store-key"
export SHOPLY_STORE_OWNER_API_SECRETE="shoply_owner_key_example123.secret-value"Cum încarc produse?
POST https://api.shoplyai.ai/merchant/products/batch?store_key=YOUR_SITECHAT_STORE_KEY
{
"source": "woocommerce-main",
"products": [
{
"external_id": "123",
"title": "Trail shoes",
"description": "Water-resistant hiking shoes.",
"url": "https://example.com/products/trail-shoes",
"currency": "USD",
"price": "49.95",
"original_price": "59.95",
"available": true,
"status": "published",
"images": ["https://example.com/images/trail-shoes.jpg"],
"categories": ["Footwear"],
"metafields": {"material": "Leather"},
"variants": [
{
"external_id": "124",
"title": "Brown / 42",
"sku": "TRAIL-BR-42",
"price": "49.95",
"available": true,
"metafields": {"color": "Brown", "size": "42"}
}
]
}
]
}Câmpuri necesare și reguli
- Câmpuri obligatorii pentru produs:
external_id,title,url,currency,priceșiavailable.statusare implicit valoareapublished. - Inventar opțional: setează
tracks_inventorylatrueși oquantitynenegativă pe produs sau pe variantă. Shoply deduce apoi disponibilitatea din stoc (quantity > 0) și stocheazătotal_inventorypentru listele din admin. sourcedenumește conexiunea catalogului (nu neapărat o platformă). Folosește un nume stabil precumwoocommerce-main. Caractere permise: litere mici, cifre, underscore și cratimă; maximum 64 de caractere. Produsele create din formular în admin folosesc implicit sursaadmin.- Identitatea produsului este combinația dintre magazin, sursă și ID extern. Operațiile upsert
POSTbatch și single sunt înlocuiri complete, nu patch-uri: câmpurile opționale omise sunt șterse. FoloseștePATCHpentru actualizări parțiale. - Batch-urile conțin între 1 și 50 de produse și cel mult 2.000.000 de bytes în cerere. JSON-ul validat al fiecărui produs este limitat la 128.000 de bytes, cu maximum 250 de variante.
- Preferă șiruri zecimale pentru prețuri. Moneda este un cod cu trei litere majuscule.
- URL-urile produselor și imaginilor trebuie să fie HTTP(S). Importul nu preia aceste URL-uri în locul tău.
- Folosește
metafieldspublice pentru specificații de produs care pot fi căutate (echivalentul SiteChat pentru metafield-urile de produs Shopify). Valorile trebuie să fie șiruri simple.attributes, varianta legacy, este acceptată ca alias.metadataprivată pentru produse nu mai este suportată. - Produsele
draftșiarchivedsunt omise din următorul index publicat. Produsele publicate, dar epuizate, rămân indexate cu informația de disponibilitate atașată. - Colecțiile manuale stochează un titlu, o descriere, un status și o listă de apartenențe de produse (
source+external_id). Colecțiile smart/bazate pe reguli nu sunt suportate în această versiune.
Exemplu de răspuns de succes
{
"results": [
{
"external_id": "123",
"product_id": "sitechat_product::woocommerce-main::<sha256-of-external-id>",
"status": "stored"
}
],
"index_status": "pending",
"index_revision": 1
}Shoply validează întreaga cerere înainte de a scrie datele. Un HTTP 200 poate totuși să listeze unele rezultate failed cu error: "storage_error". Inspectează fiecare rezultat și reîncearcă produsele eșuate. Dacă index_status este request_failed, stocarea a reușit, dar indexarea nu a fost programată — reîncearcă și produsele deja stocate.
Exemplu Python
import json
import os
import requests
store_key = os.environ["SHOPLY_STORE_KEY"]
headers = {
"Authorization": json.dumps({
"store_key": store_key,
"store_owner_api_secrete": os.environ["SHOPLY_STORE_OWNER_API_SECRETE"],
})
}
response = requests.post(
"https://api.shoplyai.ai/merchant/products/batch",
params={"store_key": store_key},
headers=headers,
json={
"source": "custom",
"products": [{
"external_id": "123",
"title": "Trail shoes",
"url": "https://example.com/products/trail-shoes",
"currency": "USD",
"price": "49.95",
"available": True,
}],
},
timeout=60,
)
response.raise_for_status()
result = response.json()
failed = [item["external_id"] for item in result["results"] if item["status"] != "stored"]
if failed:
raise RuntimeError(f"Products need retry: {failed}")
if result["index_status"] == "request_failed":
raise RuntimeError("Products saved, but retry the batch to request indexing")Cum verific un produs importat?
GET https://api.shoplyai.ai/merchant/products?store_key=YOUR_SITECHAT_STORE_KEY&source=woocommerce-main&external_id=123
Folosește același header Authorization. Răspunsul include schema_version, updated_at, index_status și product normalizat. Înregistrările lipsă returnează HTTP 404.
După ce indexatorul din fundal publică o reconstrucție, statusul de recitire per produs devine indexed, excluded (pentru produse draft sau arhivate) ori limit_exceeded. Folosește GET /merchant/products/list pentru listarea în admin. Fă soft-archive cu DELETE /merchant/products (sau setează status la archived / draft) pentru a ține un produs în afara următorului index publicat; în această versiune nu există hard-delete.
record = requests.get(
"https://api.shoplyai.ai/merchant/products",
params={
"store_key": store_key,
"source": "woocommerce-main",
"external_id": "123",
},
headers=headers,
timeout=30,
)
record.raise_for_status()
print(record.json()["index_status"], record.json()["product"]["title"])Cum actualizez în siguranță variantele sau metafield-urile?
Pentru un PATCH care conține variants, metafields sau câmpul legacy attributes, citește mai întâi produsul cu GET. Construiește modificarea pornind de la acel răspuns și include valoarea sa updated_at de nivel superior ca expected_updated_at în corpul PATCH. Acest lucru se aplică și atunci când golești variantele sau metafield-urile.
current_response = requests.get(
"https://api.shoplyai.ai/merchant/products",
params={"store_key": store_key, "source": "woocommerce-main", "external_id": "123"},
headers=headers,
timeout=30,
)
current_response.raise_for_status()
current = current_response.json()
updated_metafields = {**current["product"].get("metafields", {}), "material": "Leather"}
response = requests.patch(
"https://api.shoplyai.ai/merchant/products",
params={"store_key": store_key},
headers=headers,
json={
"source": "woocommerce-main",
"external_id": "123",
"expected_updated_at": current["updated_at"],
"metafields": updated_metafields,
},
timeout=30,
)
response.raise_for_status()HTTP 409 înseamnă că versiunea lipsea sau că o altă actualizare a modificat produsul. Citește cea mai recentă versiune a produsului și îmbină din nou modificările dorite înainte de a reîncerca. Nu atașa o versiune nouă unei liste vechi de variante: asta ar putea suprascrie valori de stoc mai noi.
Integrările existente care fac PATCH acestor câmpuri fără o versiune trebuie actualizate. Cererile PATCH doar cu scalari, ajustările dedicate de inventar și înlocuirile complete prin POST sau import batch nu necesită acest câmp. Înlocuirile complete înlocuiesc în continuare întregul produs.
Pot încărca imagini de produs?
Da. Dacă o imagine este deja disponibilă la un URL public HTTPS stabil, pune acel URL în lista images a produsului sau în câmpul image al unei variante. URL-urile publice HTTPS S3 funcționează. Căile brute s3:// și URL-urile semnate cu durată scurtă nu funcționează.
Pentru ca Shoply să găzduiască fișierul, încarcă bytes-ul brut al imaginii din backendul tău:
POST https://api.shoplyai.ai/merchant/products/images?store_key=YOUR_SITECHAT_STORE_KEY
Content-Type: image/pngTrimite bytes-ii brut ai fișierului, nu JSON, base64 sau date multipart form. Sunt acceptate JPEG, PNG și WebP, până la 10 MiB și 20 de milioane de pixeli. Imaginile animate nu sunt suportate. Shoply convertește imaginea în WebP și elimină metadatele încorporate.
with open("trail-shoes.png", "rb") as image_file:
response = requests.post(
"https://api.shoplyai.ai/merchant/products/images",
params={"store_key": store_key},
headers={**headers, "Content-Type": "image/png"},
data=image_file,
timeout=60,
)
response.raise_for_status()
image_url = response.json()["url"]HTTP 201 returnează url, content_type, size_bytes, width și height. Încărcarea unei imagini de una singură nu o atașează la un produs și nu solicită indexare. Include URL-ul returnat într-un produs complet și retrimite-l prin /merchant/products/batch.
Aceeași imagine încărcată din nou pentru același cont își reutilizează URL-ul. O imagine modificată primește un URL nou. În această versiune nu există endpoint pentru ștergerea imaginilor.
Când apar produsele în chat și căutare?
După o salvare batch reușită, Shoply solicită o reconstrucție de index în fundal. Răspunsurile raportează index_status: "pending" până când workerul publică noul index. Nu există o garanție fixă privind timpul de finalizare.
- Produsele publicate intră atât în căutarea de produse, cât și în baza de cunoștințe folosită de chatul SiteChat.
- Produsele draft și arhivate sunt excluse la următoarea reconstrucție.
- Dacă indexarea nu a fost programată (
index_status: "request_failed"), reîncearcă batch-ul pentru produsele care au fost deja stocate cu succes.
La ce erori ar trebui să mă aștept?
| HTTP status | Semnificație |
|---|---|
403 | Secret lipsă, invalid, expirat sau revocat; magazin greșit; sau un cont care nu este SiteChat |
404 | Produsul importat solicitat nu există |
413 | Cererea sau imaginea depășește limita de dimensiune |
415 | Încărcarea imaginii a folosit un Content-Type nesuportat |
422 | Câmpuri invalide, ID-uri duplicate, imagini animate sau supradimensionate ori limite ale modelului depășite |
503 | Eșec temporar de stocare |
Secretele expiră după 90 de zile. Creează un înlocuitor în Settings → Store owner API secret înainte de expirare și revocă orice secret de care nu mai ai nevoie. Același secret poate apela și endpointurile de analytics, conversation și knowledge documentate în ghidul Merchant API.
Pentru ajutor cu o integrare, contactează Shoply AI.
