PrestaShop Webservice API: integrazione REST ed ERP
Guida alla Webservice API PrestaShop — operazioni CRUD, client PHP, autenticazione, filtri, integrazione ERP/POS e anteprima AdminAPI di PS 9.
Cos’è il Webservice di PrestaShop
Il Webservice di PrestaShop è un’API REST integrata che consente alle applicazioni esterne di leggere e scrivere i dati del negozio tramite HTTP. Espone risorse — prodotti, ordini, clienti, categorie, scorte e decine di altre — attraverso un’interfaccia standardizzata. XML è il formato predefinito; JSON è disponibile da PS 1.7+ tramite il parametro &output_format=JSON.
Ogni PrestaShop dalla versione 1.4 include il Webservice. Non è un modulo — fa parte del core. PS 1.6, 1.7, 8.x e 9.x lo supportano tutti.
Il Webservice è il metodo ufficiale per integrare PrestaShop con sistemi esterni. Le query dirette al database aggirano la validazione, gli hook e la logica di business. L’API no.
Casi d’uso comuni: sincronizzazione dei prodotti da un ERP o PIM, esportazione degli ordini verso sistemi di fulfillment, mantenimento delle scorte sincronizzate tra i canali, gestione dei clienti da un CRM e automazione di operazioni massive come gli aggiornamenti dei prezzi.
Abilitazione e Configurazione dell’API
Il Webservice è disabilitato per impostazione predefinita. Abilitalo in Parametri Avanzati > Webservice, quindi clicca su “Aggiungi nuova chiave webservice”. Per ogni chiave si imposta una descrizione, lo stato abilitato/disabilitato è una matrice di permessi — una griglia di risorse e metodi HTTP consentiti (GET, POST, PUT, DELETE, HEAD).
Crea chiavi API separate per ogni integrazione. Se il tuo ERP legge solo gli ordini e aggiorna le scorte, non dargli il permesso di eliminare i prodotti. Principio del privilegio minimo.
Il Webservice richiede la riscrittura degli URL. Apache la gestisce tramite .htaccess in /api/. Su Nginx, aggiungi:
location /api/ {
try_files $uri $uri/ /webservice/dispatcher.php?$args;
}
Autenticazione
HTTP Basic Auth — la chiave API va nel campo username, la password è vuota:
curl -u "YOUR_API_KEY:" https://your-store.com/api/products
HTTPS è obbligatorio — le chiavi viaggiano in ogni header di richiesta. Il whitelisting degli IP è la singola misura di sicurezza più efficace per le integrazioni con IP fisso:
# .htaccess in /api/
<IfModule mod_authz_core.c>
Require ip 10.0.0.5
Require ip 192.168.1.0/24
</IfModule>
Ruota le chiavi ogni 6-12 mesi. Conservale nelle variabili d’ambiente, mai nel codice sorgente.
Risorse Disponibili
Chiama l’endpoint root per vedere tutto ciò a cui la tua chiave può accedere:
curl -u "KEY:" https://your-store.com/api/
Catalogo: products, combinations, categories, manufacturers, suppliers, product_features, product_feature_values, product_options (gruppi di attributi), product_option_values, tags, images
Vendite: orders, order_details (righe d’ordine), order_states, order_histories (cambi di stato), order_carriers (tracking), carts, cart_rules
Clienti: customers, addresses, groups
Inventario: stock_availables (risorsa principale per le scorte), warehouses, supply_orders
Configurazione: carriers, countries, currencies, languages, taxes, zones, shops
Operazioni CRUD
GET — Lettura dei Dati
# 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 — Creazione
Ottieni lo schema XML vuoto, compila i campi obbligatori e reinvialo con 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 — Aggiornamento
Recupera la risorsa corrente con GET, modifica i campi e reinvia l’intero XML con PUT. Gli aggiornamenti parziali non sono supportati.
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
Esegui sempre una GET prima di una PUT. Se costruisci l’XML da zero e dimentichi un campo obbligatorio, l’API potrebbe azzerarlo o rifiutare la richiesta.
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 è permanente — nessun cestino, nessun annullamento. In produzione, preferisci impostare active=0.
Filtraggio, Ordinamento e Paginazione
# 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
Scoperta dello schema — due modalità per ispezionare la struttura delle risorse senza documentazione:
?schema=blank # Empty XML template with all fields
?schema=synopsis # Field types, required flags, max lengths, read-only markers
La synopsis ti dice esattamente quali campi sono obbligatori e quale formato si aspettano. Consultala sempre prima di scrivere il codice di integrazione.
Lavorare con le Immagini
Le immagini dei prodotti vengono caricate tramite dati multipart form su un endpoint separato:
# 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"
Upload in 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);
Ottimizza le immagini prima di caricarle. Ridimensiona a massimo 2048px e comprimi — foto da 5MB scattate con reflex rallenteranno il tuo negozio.
Combinazioni e Attributi
Le combinazioni sono la parte più complessa dell’API. Il modello dati ha tre livelli:
- Product Option (gruppo di attributi) — Taglia, Colore, Materiale
- Product Option Value — S, M, L, Rosso, Blu
- Combination — un insieme di valori per un prodotto (Taglia:M + Colore:Rosso)
Crea in ordine: gruppo di attributi → valori → combinazione:
# 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"
Il price di una combinazione è un impatto sul prezzo aggiunto al prezzo base del prodotto, non il prezzo finale.
Scorte per Combinazione
Le scorte vengono gestite tramite stock_availables, non dalla combinazione stessa:
# 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"
Il record di scorta a livello di prodotto (id_product_attribute=0) contiene la somma di tutte le combinazioni. Aggiorna le scorte a livello di combinazione e PrestaShop ricalcola automaticamente il totale.
Ordini e Carrello
# 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"
Aggiornamento dello Stato dell’Ordine
Crea un nuovo record order_history — questo attiva il cambio di stato e invia l’email al cliente:
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"
ID degli stati predefiniti: 1=In attesa di pagamento, 2=Pagamento accettato, 3=In lavorazione, 4=Spedito, 5=Consegnato, 6=Annullato, 7=Rimborsato. Questi variano a seconda dell’installazione — interroga order_states per l’elenco effettivo del tuo negozio.
Numeri di tracking: Recupera con GET il record order_carriers per l’ordine, aggiungi il tracking_number e reinvialo con PUT.
Creare ordini tramite API è tecnicamente possibile ma non consigliato. La creazione dell’ordine coinvolge la validazione del carrello, il calcolo delle tasse, l’elaborazione del pagamento, la detrazione delle scorte e l’esecuzione degli hook — l’API bypassa la maggior parte di queste operazioni. Per le importazioni da marketplace, crea un carrello tramite API e processalo attraverso un front controller personalizzato.
Libreria Client PHP
composer require prestashop/prestashop-webservice-lib
Oppure scarica il file singolo da 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 . "\
";
}
// 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
]);
Pattern di Integrazione
Integrazione ERP
Lo scenario più comune. Prodotti, prezzi e scorte fluiscono dall’ERP a PrestaShop; ordini e dati dei clienti tornano indietro. Best practice: usa i codici di riferimento (SKU/EAN) come identificativi condivisi, pianifica la sincronizzazione delle scorte ogni 15 minuti e quella dei prodotti ogni ora, traccia il timestamp dell’ultima sincronizzazione con filter[date_upd], decidi in anticipo la risoluzione dei conflitti (di solito vince l’ERP) e registra tutto nei log.
Magazzino e POS
Il WMS segue un ciclo: ricevi la merce → aggiorna le scorte tramite API; interroga gli ordini → spedisci → aggiorna il tracking tramite API. L’integrazione POS è simile — le scorte devono sincronizzarsi in tempo quasi reale cosicché gli acquisti in negozio riducano immediatamente la disponibilità online.
Sincronizzazione Marketplace
Le integrazioni con Allegro, Amazon, eBay richiedono l’esportazione dei prodotti con immagini, l’importazione degli ordini (tramite carrello + elaborazione personalizzata anziché POST diretto dell’ordine) e la sincronizzazione bidirezionale delle scorte per prevenire l’overselling.
Contabilità
Sola lettura: recupera ordini, fatture e note di credito con cadenza giornaliera/settimanale. Necessita solo dei permessi GET.
Modifiche all’API in PrestaShop 9
Il Webservice legacy continua a funzionare in PS 9 — non è deprecato. Le integrazioni esistenti funzionano dopo l’aggiornamento.
AdminAPI — La Nuova API Basata su Symfony
PS 9 introduce una nuova AdminAPI accanto al Webservice legacy. Differenze principali:
- Autenticazione: OAuth2 con client credentials (vs. chiave API con Basic Auth)
- Formato: Solo JSON (vs. XML predefinito)
- Architettura: Symfony / API Platform con documentazione OpenAPI/Swagger su
/admin-api/docs - Copertura: In crescita — non copre ancora tutte le risorse del Webservice legacy
# 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
I token scadono (predefinito: 1 ora) — gestisci il refresh nella tua integrazione. Gli scope (product_read, product_write, order_read) controllano l’accesso in modo granulare. Crea i client API in Parametri Avanzati > AdminAPI.
Usa AdminAPI per le nuove integrazioni PS 9+. Usa il Webservice legacy per un’ampia copertura delle risorse o per la retrocompatibilità con PS 1.6/1.7/8.x. Puoi usare entrambi nella stessa integrazione.
Problemi Comuni
401 Unauthorized: Chiave errata (controlla gli spazi), chiave disabilitata, Webservice disattivato, oppure chiave inviata come parametro nella query anziché nell’header Basic Auth.
403 Forbidden: La chiave non ha i permessi per la risorsa o il metodo HTTP. Controlla la matrice dei permessi.
404 Not Found: La risorsa non esiste o la riscrittura degli URL non funziona. Test: curl -u "KEY:" "https://store.com/webservice/dispatcher.php?url=products" — se questo funziona ma /api/products no, correggi le regole di riscrittura.
Errori di parsing XML: Usa CDATA per i caratteri speciali (<![CDATA[HTML & more]]>), avvolgi sempre nell’elemento root <prestashop>, invia UTF-8 con l’header Content-Type appropriato.
Operazioni massive lente: L’API elabora una richiesta alla volta. Per 10.000+ elementi:
- Richiedi solo i campi necessari con
display— evitadisplay=fullsu cataloghi grandi - Filtra per
date_updper sincronizzare solo i record modificati - Riutilizza gli handle curl per connessioni persistenti
- Per importazioni iniziali di 50K+ elementi, considera l’accesso diretto al DB con svuotamento della 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);
Best Practice di Sicurezza
- Una chiave per integrazione — revocane una senza compromettere le altre
- Permessi minimi — la sincronizzazione delle scorte non ha bisogno del DELETE sui prodotti
- Sempre HTTPS — le chiavi in HTTP in chiaro sono visibili agli sniffer di rete
- Whitelisting degli IP — la singola misura più efficace per le integrazioni server-to-server
- Rotazione delle chiavi — ogni 6-12 mesi
- Variabili d’ambiente — non committare mai le chiavi nel controllo di versione
- Rate limiting — l’API non ne ha uno integrato; aggiungilo a livello di web server
# 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;
}
Registrazione degli accessi: PrestaShop non ha un logging API integrato. Analizza i log di accesso del web server per le richieste a /api/, oppure sovrascrivi WebserviceRequest per registrare timestamp, IP, risorsa, metodo e codice di risposta. Essenziale per la conformità GDPR/PCI quando si accede ai dati dei clienti.
Alternative al Webservice
Accesso Diretto al Database
Ordini di grandezza più veloce per le operazioni massive, ma bypassa la validazione, gli hook e l’invalidazione della cache. Appropriato per importazioni una tantum, reportistica in sola lettura e correzioni di emergenza. Non appropriato per la sincronizzazione continua o qualsiasi operazione che tocchi ordini o pagamenti. Svuota sempre le cache dopo le modifiche dirette al DB.
Hook dei Moduli per la Sincronizzazione in Tempo Reale
Invece di interrogare l’API con il polling, invia i dati tramite hook quando si verificano gli eventi:
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);
}
Endpoint Personalizzati dei Moduli
Per le operazioni che il Webservice gestisce male, costruisci un’API personalizzata come front controller di un modulo. Controllo completo su formato, autenticazione e logica di business — elabora operazioni massive in una singola richiesta utilizzando le classi native di PrestaShop per la validazione.
Scegliere l’Approccio Giusto
| Scenario | Approccio Migliore |
|---|---|
| Integrazione ERP/WMS standard | Webservice API |
| Nuova integrazione PS 9+ | AdminAPI (OAuth2, JSON) |
| Importazione massiva di 50K+ prodotti | DB diretto + svuotamento cache |
| Sincronizzazione eventi in tempo reale | Hook dei moduli (push webhook) |
| Logica di business personalizzata | Endpoint personalizzato del modulo |
| Reportistica in sola lettura | Query dirette al DB |
Il Webservice di PrestaShop è stabile da oltre un decennio. Per PS 9+, AdminAPI offre un’alternativa moderna. Scegli lo strumento giusto per ogni esigenza, implementalo con sicurezza e gestione degli errori fin dal primo giorno, e testa sempre sulla versione specifica di PrestaShop che stai utilizzando.
Related: Smart Google Merchant Feed Manager · Hooks & Overrides Guide · Analytics for Online Stores (Blog)