Knowledge Base Guide

API Webservice PrestaShop: Integracja REST, klient PHP i synchronizacja ERP

Kompletny przewodnik po PrestaShop Webservice API — operacje CRUD, biblioteka PHP, uwierzytelnianie, filtrowanie, integracja ERP/POS i AdminAPI w PS 9.

Czym jest PrestaShop Webservice

PrestaShop Webservice to wbudowane API typu REST, które umożliwia zewnętrznym aplikacjom odczytywanie i zapisywanie danych sklepu przez HTTP. Udostępnia zasoby — produkty, zamówienia, klientów, kategorie, stany magazynowe i dziesiątki innych — poprzez ustandaryzowany interfejs. Domyślnym formatem jest XML; JSON jest dostępny w PS 1.7+ za pomocą parametru &output_format=JSON.

Każdy PrestaShop od wersji 1.4 zawiera Webservice. To nie jest moduł — to część rdzenia systemu. PS 1.6, 1.7, 8.x i 9.x — wszystkie go obsługują.

Webservice to oficjalny sposób integracji PrestaShop z zewnętrznymi systemami. Bezpośrednie zapytania do bazy danych pomijają walidację, hooki i logikę biznesową. API tego nie robi.

Typowe zastosowania: synchronizacja produktów z ERP lub PIM, eksport zamówień do systemów realizacji, utrzymywanie spójności stanów magazynowych między kanałami, zarządzanie klientami z CRM oraz automatyzacja operacji masowych, takich jak aktualizacja cen.

Włączanie i konfiguracja API

Webservice jest domyślnie wyłączony. Włącz go w Zaawansowane > Webservice, a następnie kliknij „Dodaj nowy klucz webservice”. Dla każdego klucza ustawiasz opis, status włączony/wyłączony oraz macierz uprawnień — siatkę zasobów i dozwolonych metod HTTP (GET, POST, PUT, DELETE, HEAD).

Twórz oddzielne klucze API dla każdej integracji. Jeśli Twój ERP tylko odczytuje zamówienia i aktualizuje stany magazynowe, nie dawaj mu uprawnień do usuwania produktów. Zasada minimalnych uprawnień.

Webservice wymaga przepisywania URL-i. Apache obsługuje to przez .htaccess w /api/. W przypadku Nginx dodaj:

location /api/ {
    try_files $uri $uri/ /webservice/dispatcher.php?$args;
}

Uwierzytelnianie

HTTP Basic Auth — klucz API wpisuje się w pole nazwy użytkownika, hasło pozostaje puste:

curl -u "YOUR_API_KEY:" https://your-store.com/api/products

HTTPS jest obowiązkowy — klucze są przesyłane w każdym nagłówku żądania. Biała lista IP to najskuteczniejszy pojedynczy środek bezpieczeństwa dla integracji ze stałym adresem IP:

# .htaccess in /api/
<IfModule mod_authz_core.c>
    Require ip 10.0.0.5
    Require ip 192.168.1.0/24
</IfModule>

Rotuj klucze co 6-12 miesięcy. Przechowuj je w zmiennych środowiskowych, nigdy w kodzie źródłowym.

Dostępne zasoby

Wywołaj główny endpoint, aby zobaczyć wszystko, do czego Twój klucz ma dostęp:

curl -u "KEY:" https://your-store.com/api/

Katalog: products, combinations, categories, manufacturers, suppliers, product_features, product_feature_values, product_options (grupy atrybutów), product_option_values, tags, images

Sprzedaż: orders, order_details (pozycje zamówienia), order_states, order_histories (zmiany statusów), order_carriers (śledzenie przesyłek), carts, cart_rules

Klienci: customers, addresses, groups

Magazyn: stock_availables (główny zasób magazynowy), warehouses, supply_orders

Konfiguracja: carriers, countries, currencies, languages, taxes, zones, shops

Operacje CRUD

GET — Odczyt danych

# List products (IDs only)
curl -u "KEY:" https://your-store.com/api/products

# Full details
curl -u "KEY:" "https://your-store.com/api/products?display=full"

# Selected fields only (faster)
curl -u "KEY:" "https://your-store.com/api/products?display=[id,name,price,reference]"

# Single product in JSON
curl -u "KEY:" "https://your-store.com/api/products/42?output_format=JSON"

POST — Tworzenie

Pobierz pusty schemat XML, wypełnij wymagane pola i wyślij go z powrotem metodą POST:

curl -u "KEY:" -X POST -H "Content-Type: application/xml" \
  -d '<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
  <product>
    <id_category_default>2</id_category_default>
    <id_tax_rules_group>1</id_tax_rules_group>
    <active>1</active><state>1</state>
    <price>29.99</price>
    <name><language id="1">My Product</language></name>
    <link_rewrite><language id="1">my-product</language></link_rewrite>
    <description_short><language id="1">Short desc</language></description_short>
    <associations><categories><category><id>2</id></category></categories></associations>
  </product>
</prestashop>' https://your-store.com/api/products

PUT — Aktualizacja

Pobierz aktualny zasób metodą GET, zmodyfikuj pola i wyślij cały XML z powrotem metodą PUT. Częściowe aktualizacje nie są obsługiwane.

curl -u "KEY:" https://your-store.com/api/products/42 -o product.xml
# Edit product.xml, then:
curl -u "KEY:" -X PUT -H "Content-Type: application/xml" \
     -d @product.xml https://your-store.com/api/products/42
Zawsze wykonaj GET przed PUT. Jeśli skonstruujesz XML od zera i zapomnisz wymaganego pola, API może je wyczyścić lub odrzucić żądanie.

DELETE

curl -u "KEY:" -X DELETE https://your-store.com/api/products/42
# Multiple: DELETE "https://your-store.com/api/products/?id=[42|43|44]"

DELETE jest trwałe — bez kosza, bez cofania. W środowisku produkcyjnym lepiej ustawić active=0.

Filtrowanie, sortowanie i paginacja

# Exact match
?filter[reference]=ABC-123

# Range (price 10-50)
?filter[price]=[10,50]

# Date range
?filter[date_upd]=[2025-01-01,2025-12-31]

# Starts with (% URL-encoded as %25)
?filter[name]=[Nike]%25

# Combined
?filter[active]=1&filter[id_category_default]=5&display=[id,name,price]

# Sorting
?sort=[price_ASC]    ?sort=[date_upd_DESC]

# Pagination (offset,count)
?limit=50         # first 50
?limit=50,50      # results 51-100

Odkrywanie schematu — dwa tryby pozwalają zbadać strukturę zasobu bez dokumentacji:

?schema=blank     # Empty XML template with all fields
?schema=synopsis  # Field types, required flags, max lengths, read-only markers

Synopsis powie Ci dokładnie, które pola są wymagane i jakiego formatu oczekują. Zawsze sięgaj do niego przed pisaniem kodu integracji.

Praca z obrazami

Obrazy produktów są przesyłane za pomocą danych multipart do osobnego endpointu:

# Upload
curl -u "KEY:" -X POST -F "image=@photo.jpg;type=image/jpeg" \
     "https://your-store.com/api/images/products/42"

# List images for product
curl -u "KEY:" "https://your-store.com/api/images/products/42"

# Get specific image / image type
curl -u "KEY:" "https://your-store.com/api/images/products/42/15/large_default"

# Delete
curl -u "KEY:" -X DELETE "https://your-store.com/api/images/products/42/15"

Przesyłanie w PHP:

$ch = curl_init("$shopUrl/api/images/products/$productId");
curl_setopt($ch, CURLOPT_USERPWD, "$apiKey:");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'image' => new CURLFile($imagePath, mime_content_type($imagePath))
]);
$response = curl_exec($ch);
Optymalizuj obrazy przed przesyłaniem. Zmniejsz do maksymalnie 2048px i skompresuj — zdjęcia 5MB z lustrzanki spowolnią Twój sklep.

Kombinacje i atrybuty

Kombinacje to najtrudniejsza część API. Model danych ma trzy warstwy:

  • Product Option (grupa atrybutów) — Rozmiar, Kolor, Materiał
  • Product Option Value — S, M, L, Czerwony, Niebieski
  • Combination — zestaw wartości dla produktu (Rozmiar:M + Kolor:Czerwony)

Tworzenie w kolejności: grupa atrybutów → wartości → kombinacja:

# Create combination linking to existing attribute values
curl -u "KEY:" -X POST -H "Content-Type: application/xml" \
  -d '<prestashop><combination>
    <id_product>42</id_product>
    <reference>PROD-42-M-RED</reference>
    <price>5.00</price>
    <minimal_quantity>1</minimal_quantity>
    <associations><product_option_values>
      <product_option_value><id>2</id></product_option_value>
      <product_option_value><id>7</id></product_option_value>
    </product_option_values></associations>
  </combination></prestashop>' "https://your-store.com/api/combinations"

Pole price w kombinacji to wpływ na cenę dodawany do bazowej ceny produktu, a nie cena końcowa.

Stan magazynowy per kombinacja

Stan magazynowy jest zarządzany przez stock_availables, a nie przez samą kombinację:

# Find stock record
curl -u "KEY:" "https://your-store.com/api/stock_availables?filter[id_product]=42&filter[id_product_attribute]=15&display=full"

# Update (GET first, modify quantity, PUT back)
curl -u "KEY:" -X PUT -H "Content-Type: application/xml" \
  -d '<prestashop><stock_available>
    <id>89</id><id_product>42</id_product>
    <id_product_attribute>15</id_product_attribute>
    <quantity>100</quantity>
  </stock_available></prestashop>' "https://your-store.com/api/stock_availables/89"
Rekord magazynowy na poziomie produktu (id_product_attribute=0) przechowuje sumę wszystkich kombinacji. Aktualizuj stan magazynowy na poziomie kombinacji, a PrestaShop automatycznie przeliczy sumę.

Zamówienia i koszyk

# Recent orders
curl -u "KEY:" "https://your-store.com/api/orders?display=[id,reference,total_paid,current_state,date_add]&sort=[id_DESC]&limit=20"

# Full order with line items
curl -u "KEY:" "https://your-store.com/api/orders/1234?display=full"
curl -u "KEY:" "https://your-store.com/api/order_details?filter[id_order]=1234&display=full"

Aktualizacja statusu zamówienia

Utwórz nowy rekord order_history — to uruchamia zmianę statusu i wysyła e-mail do klienta:

curl -u "KEY:" -X POST -H "Content-Type: application/xml" \
  -d '<prestashop><order_history>
    <id_order>1234</id_order>
    <id_order_state>4</id_order_state>
  </order_history></prestashop>' "https://your-store.com/api/order_histories"

Domyślne ID statusów: 1=Oczekiwanie na płatność, 2=Płatność zaakceptowana, 3=W realizacji, 4=Wysłane, 5=Dostarczone, 6=Anulowane, 7=Zwrócone. Mogą się różnić w zależności od instalacji — sprawdź order_states dla listy właściwej dla Twojego sklepu.

Numery śledzenia: Pobierz rekord order_carriers dla zamówienia metodą GET, dodaj tracking_number, wyślij z powrotem metodą PUT.

Tworzenie zamówień przez API jest technicznie możliwe, ale niezalecane. Tworzenie zamówienia obejmuje walidację koszyka, obliczanie podatków, przetwarzanie płatności, odejmowanie stanu magazynowego i wykonywanie hooków — API pomija większość z tego. Przy importach z marketplace utwórz koszyk przez API i przetwórz go przez dedykowany front controller.

Biblioteka klienta PHP

composer require prestashop/prestashop-webservice-lib

Lub pobierz pojedynczy plik z GitHub.

$ws = new PrestaShopWebservice('https://your-store.com', 'API_KEY', false);

// List products
$xml = $ws->get(['resource' => 'products', 'display' => 'full', 'limit' => 10]);
foreach ($xml->products->product as $p) {
    echo $p->id . ' - ' . $p->name->language . "\n";
}

// Create product from blank schema
$blank = $ws->get(['url' => 'https://your-store.com/api/products?schema=blank']);
$blank->product->active = 1;
$blank->product->price = 29.99;
$blank->product->name->language[0] = 'New Product';
$blank->product->name->language[0]['id'] = 1;
$blank->product->link_rewrite->language[0] = 'new-product';
$blank->product->link_rewrite->language[0]['id'] = 1;
$blank->product->id_category_default = 2;
$result = $ws->add(['resource' => 'products', 'postXml' => $blank->asXML()]);

// Update stock
function updateStock($ws, int $pid, int $qty, int $combo = 0): void {
    $xml = $ws->get([
        'resource' => 'stock_availables',
        'filter[id_product]' => $pid,
        'filter[id_product_attribute]' => $combo,
        'display' => 'full'
    ]);
    $sid = (int)$xml->stock_availables->stock_available->id;
    $sxml = $ws->get(['resource' => 'stock_availables', 'id' => $sid]);
    $sxml->stock_available->quantity = $qty;
    $ws->edit(['resource' => 'stock_availables', 'id' => $sid, 'putXml' => $sxml->asXML()]);
}

// Export orders since date
$xml = $ws->get([
    'resource' => 'orders',
    'display' => '[id,reference,total_paid,current_state,date_add]',
    'filter[date_add]' => '[2025-06-01,9999-12-31]',
    'sort' => '[date_add_DESC]', 'limit' => 500
]);

Wzorce integracji

Integracja z ERP

Najczęstszy scenariusz. Produkty, ceny i stany magazynowe płyną z ERP do PrestaShop; zamówienia i dane klientów wracają w drugą stronę. Dobre praktyki: używaj kodów referencyjnych (SKU/EAN) jako wspólnych identyfikatorów, planuj synchronizację stanów co 15 minut, a produktów co godzinę, śledź znacznik czasu ostatniej synchronizacji za pomocą filter[date_upd], z góry ustal zasady rozwiązywania konfliktów (zwykle wygrywa ERP) i loguj wszystko.

Magazyn i POS

WMS działa w cyklu: przyjęcie towaru → aktualizacja stanu przez API; odpytywanie zamówień → wysyłka → aktualizacja śledzenia przesyłki przez API. Integracja POS jest podobna — stany muszą się synchronizować niemal w czasie rzeczywistym, aby zakupy w sklepie stacjonarnym natychmiast zmniejszały dostępność online.

Synchronizacja z marketplace

Integracje z Allegro, Amazon, eBay wymagają eksportu produktów z obrazami, importu zamówień (przez koszyk + niestandardowe przetwarzanie zamiast bezpośredniego POST zamówienia) oraz dwukierunkowej synchronizacji stanów magazynowych, aby zapobiec nadsprzedaży.

Księgowość

Tryb tylko do odczytu: pobieraj zamówienia, faktury i korekty według dziennego/tygodniowego harmonogramu. Wymaga jedynie uprawnień GET.

Zmiany API w PrestaShop 9

Starszy Webservice nadal działa w PS 9 — nie został oznaczony jako przestarzały. Istniejące integracje działają po aktualizacji.

AdminAPI — Nowe API oparte na Symfony

PS 9 wprowadza nowe AdminAPI obok starego Webservice. Kluczowe różnice:

  • Uwierzytelnianie: OAuth2 z client credentials (zamiast Basic Auth z kluczem API)
  • Format: Wyłącznie JSON (zamiast domyślnego XML)
  • Architektura: Symfony / API Platform z dokumentacją OpenAPI/Swagger pod /admin-api/docs
  • Pokrycie: Rosnące — nie obejmuje jeszcze wszystkich zasobów starego Webservice
# Get OAuth2 token
curl -X POST https://your-store.com/admin-api/access_token \
     -d "grant_type=client_credentials&client_id=ID&client_secret=SECRET"

# Use bearer token
curl -H "Authorization: Bearer eyJ0eXAi..." https://your-store.com/admin-api/products

Tokeny wygasą (domyślnie: 1 godzina) — obsłuż odświeżanie w swojej integracji. Zakresy (product_read, product_write, order_read) kontrolują dostęp w sposób granularny. Tworzenie klientów API: Zaawansowane > AdminAPI.

Używaj AdminAPI do nowych integracji z PS 9+. Używaj starego Webservice dla szerokiego pokrycia zasobów lub wstecznej kompatybilności z PS 1.6/1.7/8.x. Możesz używać obu w tej samej integracji.

Typowe problemy

401 Unauthorized: Zły klucz (sprawdź białe znaki), klucz wyłączony, Webservice wyłączony lub klucz wysłany jako parametr URL zamiast nagłówka Basic Auth.

403 Forbidden: Klucz nie ma uprawnień do zasobu lub metody HTTP. Sprawdź macierz uprawnień.

404 Not Found: Zasób nie istnieje lub przepisywanie URL jest uszkodzone. Test: curl -u "KEY:" "https://store.com/webservice/dispatcher.php?url=products" — jeśli to działa, ale /api/products nie, napraw reguły przepisywania.

Błędy parsowania XML: Używaj CDATA dla znaków specjalnych (<![CDATA[HTML & more]]>), zawsze opakowuj w element główny <prestashop>, wysyłaj UTF-8 z właściwym nagłówkiem Content-Type.

Wolne operacje masowe: API przetwarza jedno żądanie naraz. Przy 10 000+ elementów:

  • Żądaj tylko potrzebnych pól za pomocą display — unikaj display=full na dużych katalogach
  • Filtruj po date_upd, aby synchronizować tylko zmienione rekordy
  • Używaj ponownie uchwytów curl dla połączeń trwałych
  • Przy początkowych importach 50K+ produktów rozważ bezpośredni dostęp do bazy z czyszczeniem cache
// Efficient bulk stock update — reuse handle
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, "$apiKey:");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/xml']);
foreach ($updates as $stockId => $qty) {
    curl_setopt($ch, CURLOPT_URL, "$url/api/stock_availables/$stockId");
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS,
        "<prestashop><stock_available><id>$stockId</id><quantity>$qty</quantity></stock_available></prestashop>");
    curl_exec($ch);
}
curl_close($ch);

Najlepsze praktyki bezpieczeństwa

  • Jeden klucz na integrację — możesz odwołać jeden bez wpływu na pozostałe
  • Minimalne uprawnienia — synchronizacja stanów nie potrzebuje DELETE na produktach
  • Zawsze HTTPS — klucze w czystym HTTP są widoczne dla podsuchujących sieć
  • Biała lista IP — najskuteczniejszy pojedynczy środek dla integracji serwer-serwer
  • Rotacja kluczy — co 6-12 miesięcy
  • Zmienne środowiskowe — nigdy nie commituj kluczy do repozytorium
  • Limitowanie zapytań — API nie ma wbudowanego limitu; dodaj go na poziomie serwera WWW
# Nginx rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
location /api/ {
    limit_req zone=api burst=50 nodelay;
    try_files $uri $uri/ /webservice/dispatcher.php?$args;
}

Logowanie audytowe: PrestaShop nie ma wbudowanego logowania API. Parsuj logi dostępu serwera WWW pod kątem zapytań do /api/ lub nadpisz WebserviceRequest, aby logować znacznik czasu, IP, zasób, metodę i kod odpowiedzi. Niezbędne dla zgodności z GDPR/PCI, gdy uzyskiwany jest dostęp do danych klientów.

Alternatywy dla Webservice

Bezpośredni dostęp do bazy danych

Rzędy wielkości szybszy przy operacjach masowych, ale pomija walidację, hooki i inwalidację cache. Odpowiedni do jednorazowych importów, raportów tylko do odczytu i napraw awaryjnych. Nieodpowiedni do bieżącej synchronizacji ani do operacji dotyczących zamówień czy płatności. Po zmianach bezpośrednio w bazie zawsze czyść cache.

Hooki modułowe do synchronizacji w czasie rzeczywistym

Zamiast odpytywać API, wysyłaj dane przez hooki w momencie wystąpienia zdarzeń:

public function hookActionProductUpdate($params) {
    $product = $params['product'];
    $payload = json_encode([
        'id' => $product->id, 'reference' => $product->reference,
        'price' => $product->price,
        'quantity' => StockAvailable::getQuantityAvailableByProduct($product->id),
    ]);
    $ch = curl_init('https://erp.example.com/webhook/product-update');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_exec($ch); curl_close($ch);
}

Niestandardowe endpointy modułowe

Dla operacji, z którymi Webservice radzi sobie słabo, zbuduj własne API jako front controller modułu. Pełna kontrola nad formatem, uwierzytelnianiem i logiką biznesową — przetwarzaj operacje masowe w jednym żądaniu, korzystając z natywnych klas PrestaShop do walidacji.

Wybór właściwego podejścia

ScenariuszNajlepsze podejście
Standardowa integracja ERP/WMSWebservice API
Nowa integracja z PS 9+AdminAPI (OAuth2, JSON)
Import masowy 50K+ produktówBezpośrednia baza + czyszczenie cache
Synchronizacja zdarzeń w czasie rzeczywistymHooki modułowe (webhook push)
Niestandardowa logika biznesowaNiestandardowy endpoint modułu
Raporty tylko do odczytuBezpośrednie zapytania do bazy

PrestaShop Webservice jest stabilne od ponad dekady. Dla PS 9+ AdminAPI oferuje nowoczesną alternatywę. Wybierz odpowiednie narzędzie do każdego zadania, wdrażaj z uwzględnieniem bezpieczeństwa i obsługi błędów od pierwszego dnia i zawsze testuj na konkretnej wersji PrestaShop, na którą celujesz.

More guides available

Browse our knowledge base for more practical PrestaShop tutorials, or reach out if you need help.

Ładowanie...
Powrót do góry