Jak przesłać katalog do SiteChat
Jeśli używasz SiteChat na własnej stronie internetowej (a nie w sklepie Shopify), możesz przesyłać ustrukturyzowane rekordy produktów do Shoply, aby klienci mogli je znaleźć na czacie SiteChat i w wyszukiwarce produktów.
Te endpointy używają tego samego Settings → Store owner API secret co reszta Shoply Merchant API, a strona Product Catalog w panelu administracyjnym SiteChat może je wywoływać przy użyciu tokenu dostępu administratora zalogowanego użytkownika. Sklepy Shopify nadal synchronizują dane katalogowe przez Shopify; te trasy przesyłania są dostępne tylko dla kont SiteChat, które nie synchronizują już katalogu Magento.
W panelu administracyjnym SiteChat sekcja Product Catalog otwiera obszar w stylu Shopify z zakładkami Products, Collections i Inventory. Możesz dodawać lub edytować produkty, importować pliki CSV/Excel, grupować produkty w ręczne kolekcje i dostosowywać stany magazynowe.
Jakie interfejsy API są dostępne?
| API | Metoda | Do czego służy |
|---|---|---|
/merchant/products/batch | POST | Tworzy lub całkowicie zastępuje do 50 produktów w jednym żądaniu |
/merchant/products | POST | Tworzy lub całkowicie zastępuje jeden produkt |
/merchant/products | GET | Odczytuje jeden zaimportowany produkt na podstawie source i external_id |
/merchant/products | PATCH | Częściowo aktualizuje jeden produkt; zastępowanie wariantów lub metafields wymaga wersji z GET |
/merchant/products | DELETE | Miękko archiwizuje produkt (status=archived) |
/merchant/products/list | GET | Stronicuje zaimportowane produkty na potrzeby tabel administracyjnych |
/merchant/products/images | POST | Przesyła obraz produktu i zwraca publiczny adres HTTPS |
/merchant/collections | GET / POST | Wyświetla listę ręcznych kolekcji lub tworzy nową |
/merchant/collections/{id} | GET / PUT / DELETE | Odczytuje, zastępuje lub archiwizuje jedną kolekcję |
/merchant/inventory | GET | Wyświetla wiersze stanów magazynowych (ilości produktów i wariantów) |
/merchant/inventory/adjust | POST | Ustawia śledzoną ilość dla produktu lub wariantu |
Pomyślne zapisy produktów powodują, że Shoply przebudowuje indeks sklepu. Dopóki ta przebudowa się nie zakończy, odpowiedzi będą zgłaszać index_status: "pending". Opublikowane produkty pojawią się wtedy zarówno w indeksie produktów, jak i w bazie wiedzy używanej przez czat SiteChat.
Kto może korzystać z tych interfejsów API?
- Twój sklep musi być kontem SiteChat (
app_platformto SiteChat). - Klucze sklepu Shopify (w tym dowolna domena
*.myshopify.com) są odrzucane. - Uwierzytelnianie musi używać albo prawidłowego tajnego klucza API właściciela sklepu, albo tokenu dostępu administratora SiteChat dla dokładnego
store_keypodanego w żądaniu. - Tokeny Shopify Admin API nie mogą wywoływać tych tras.
Utwórz lub obróć tajny klucz właściciela w taki sam sposób jak w przypadku innych integracji Merchant API: Jak używać Shoply Merchant API. W konsoli administracyjnej SiteChat otwórz Product Catalog, aby zarządzać produktami, kolekcjami i stanem magazynowym — lub zaimportować plik CSV albo Excel — bez samodzielnego zarządzania tajnym kluczem.
Jak działa uwierzytelnianie?
Z konektora serwerowego
Wywołuj API z zaufanego backendu przez HTTPS. Umieść ciąg JSON w nagłówku Authorization:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"store_owner_api_secrete": "YOUR_STORE_OWNER_API_SECRET"
}store_owner_api_secrete to publiczna nazwa pola, łącznie z historyczną pisownią. store_owner_api_secret jest również akceptowane. To nie jest token Bearer.
Z panelu administracyjnego SiteChat
Strona Product Catalog zamiast tego wysyła sesję administratora zalogowanego użytkownika:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN"
}access_token jest akceptowany jako alias dla admin_auth_token.
Parametr zapytania store_key musi odpowiadać nagłówkowi. Przechowuj tajne klucze właściciela wyłącznie w zmiennych środowiskowych po stronie serwera — nigdy w skrypcie storefrontu, adresie URL ani publicznym repozytorium.
export SHOPLY_STORE_KEY="your-sitechat-store-key"
export SHOPLY_STORE_OWNER_API_SECRETE="shoply_owner_key_example123.secret-value"Jak przesłać produkty?
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"}
}
]
}
]
}Wymagane pola i zasady
- Wymagane pola produktu:
external_id,title,url,currency,priceiavailable.statusdomyślnie ma wartośćpublished. - Opcjonalna kontrola stanu magazynowego: ustaw
tracks_inventorynatrueoraz nieujemnequantitydla produktu lub wariantu. Shoply wyprowadzi wtedy dostępność ze stanu magazynowego (quantity > 0) i zapiszetotal_inventoryna potrzeby list administracyjnych. sourceokreśla połączenie katalogu (niekoniecznie platformę). Używaj stabilnej nazwy, takiej jakwoocommerce-main. Dozwolone znaki: małe litery, cyfry, podkreślenia i myślniki; maksymalnie 64 znaki. Produkty utworzone przez formularz w panelu administracyjnym domyślnie mają źródłoadmin.- Tożsamość produktu jest kombinacją sklepu, źródła i zewnętrznego identyfikatora. Upserty
POSTpojedyncze i wsadowe są pełnymi zastąpieniami, a nie poprawkami: pominięte pola opcjonalne są czyszczone. UżyjPATCHdo częściowych aktualizacji. - Partie zawierają od 1 do 50 produktów i maksymalnie 2 000 000 bajtów żądania. Zweryfikowany JSON każdego produktu jest ograniczony do 128 000 bajtów, z maksymalnie 250 wariantami.
- Dla cen preferowane są dziesiętne ciągi znaków. Waluta to trzyliterowy kod zapisany wielkimi literami.
- Adresy URL produktów i obrazów muszą używać HTTP(S). Import nie pobiera tych adresów URL za Ciebie.
- Używaj publicznych
metafieldsdla przeszukiwalnych specyfikacji produktu (odpowiednik metafields produktów Shopify w SiteChat). Wartości muszą być zwykłymi ciągami znaków. Starsze poleattributesjest akceptowane jako alias. Prywatnemetadataproduktu nie są już obsługiwane. - Produkty
draftiarchivedsą pomijane przy następnym publikowanym indeksie. Wyprzedane opublikowane produkty pozostają zindeksowane z dołączoną informacją o dostępności. - Ręczne kolekcje przechowują tytuł, opis, status i listę przynależności produktów (
source+external_id). Kolekcje inteligentne/oparte na regułach nie są obsługiwane w tej wersji.
Przykładowa odpowiedź sukcesu
{
"results": [
{
"external_id": "123",
"product_id": "sitechat_product::woocommerce-main::<sha256-of-external-id>",
"status": "stored"
}
],
"index_status": "pending",
"index_revision": 1
}Shoply waliduje całe żądanie przed zapisem. HTTP 200 nadal może zawierać niektóre wyniki failed z error: "storage_error". Sprawdź każdy wynik i ponów próbę dla nieudanych produktów. Jeśli index_status ma wartość request_failed, zapis się powiódł, ale indeksowanie nie zostało zaplanowane — ponów próbę również dla zapisanych produktów.
Przykład w Pythonie
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")Jak zweryfikować zaimportowany produkt?
GET https://api.shoplyai.ai/merchant/products?store_key=YOUR_SITECHAT_STORE_KEY&source=woocommerce-main&external_id=123
Użyj tego samego nagłówka Authorization. Odpowiedź zawiera schema_version, updated_at, index_status oraz znormalizowany product. Brakujące rekordy zwracają HTTP 404.
Po opublikowaniu przebudowy przez indeksator działający w tle status odczytu dla pojedynczego produktu przyjmuje wartość indexed, excluded (dla produktów w stanie draft lub archived) albo limit_exceeded. Użyj GET /merchant/products/list do listowania administracyjnego. Miękko archiwizuj przez DELETE /merchant/products (lub ustaw status na archived / draft), aby produkt nie trafił do następnego opublikowanego indeksu; w tej wersji nie ma trwałego usuwania.
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"])Jak bezpiecznie aktualizować warianty lub metafields?
W przypadku żądania PATCH zawierającego variants, metafields lub starsze pole attributes najpierw odczytaj produkt za pomocą GET. Zbuduj edycję na podstawie tej odpowiedzi i dołącz jej wartość najwyższego poziomu updated_at jako expected_updated_at w treści PATCH. Dotyczy to również czyszczenia wariantów lub metafields.
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 oznacza, że wersja nie została podana lub inna aktualizacja zmieniła produkt. Odczytaj najnowszą wersję produktu i ponownie połącz swoje zamierzone zmiany przed ponowieniem próby. Nie dołączaj nowej wersji do starej listy wariantów: mogłoby to nadpisać nowsze wartości stanów magazynowych.
Istniejące integracje, które wykonują PATCH tych pól bez wersji, muszą zostać zaktualizowane. Żądania PATCH tylko dla wartości skalarnych, dedykowane korekty stanów magazynowych oraz pełne zastąpienia przez POST lub import wsadowy nie wymagają tego pola. Pełne zastąpienia nadal zastępują cały produkt.
Czy mogę przesyłać obrazy produktów?
Tak. Jeśli obraz jest już dostępny pod trwałym publicznym adresem HTTPS, umieść ten adres URL na liście images produktu lub w polu image wariantu. Publiczne adresy HTTPS z S3 działają. Surowe ścieżki s3:// i krótkotrwałe podpisane adresy URL nie działają.
Aby Shoply hostowało plik, prześlij surowe bajty obrazu ze swojego backendu:
POST https://api.shoplyai.ai/merchant/products/images?store_key=YOUR_SITECHAT_STORE_KEY
Content-Type: image/pngWyślij surowe bajty pliku, a nie JSON, base64 ani dane formularza multipart. Akceptowane są JPEG, PNG i WebP, do 10 MiB i 20 milionów pikseli. Obrazy animowane nie są obsługiwane. Shoply konwertuje obraz do WebP i usuwa osadzone metadane.
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 zwraca url, content_type, size_bytes, width i height. Samo przesłanie obrazu nie przypisuje go do produktu ani nie powoduje żądania indeksowania. Umieść zwrócony adres URL w kompletnym produkcie i prześlij go ponownie przez /merchant/products/batch.
Ponowne przesłanie tego samego obrazu dla tego samego konta powoduje ponowne użycie jego adresu URL. Zmieniony obraz otrzymuje nowy adres URL. W tej wersji nie ma endpointu do usuwania obrazów.
Kiedy produkty pojawiają się na czacie i w wyszukiwarce?
Po pomyślnym zapisie partii Shoply zleca przebudowę indeksu w tle. Odpowiedzi zgłaszają index_status: "pending", dopóki worker nie opublikuje nowego indeksu. Nie ma gwarancji stałego czasu zakończenia.
- Opublikowane produkty trafiają zarówno do wyszukiwania produktów, jak i do bazy wiedzy używanej przez czat SiteChat.
- Produkty draft i archived są wykluczane przy następnej przebudowie.
- Jeśli indeksowanie nie zostało zaplanowane (
index_status: "request_failed"), ponów próbę partii dla produktów, które zostały już pomyślnie zapisane.
Jakich błędów powinienem się spodziewać?
| HTTP status | Znaczenie |
|---|---|
403 | Brakujący, nieprawidłowy, wygasły lub cofnięty secret; zły sklep; albo konto niebędące kontem SiteChat |
404 | Żądany zaimportowany produkt nie istnieje |
413 | Żądanie lub obraz przekracza limit rozmiaru |
415 | Przesyłanie obrazu użyło nieobsługiwanego Content-Type |
422 | Nieprawidłowe pola, zduplikowane identyfikatory, animowane lub zbyt duże obrazy albo przekroczone limity modelu |
503 | Tymczasowa awaria zapisu |
Sekrety wygasają po 90 dniach. Utwórz zamiennik w Settings → Store owner API secret przed wygaśnięciem i cofnij każdy secret, którego już nie potrzebujesz. Ten sam secret może również wywoływać endpointy analityczne, konwersacyjne i wiedzy udokumentowane w przewodniku Merchant API.
Aby uzyskać pomoc przy integracji, skontaktuj się z Shoply AI.
