Orientações de Integração — SOAP API Magento 1
Leitura em lote de preço e estoque (módulo MageShop_BatchProductInfo)
Documento de referência para integrações ERP ↔ Magento 1 que precisam coletar preço e estoque de muitos produtos em poucas chamadas. Expõe um método SOAP v2 customizado que substitui o par clássico catalogProductInfo + cataloginventoryStockItemList.
1. Contexto
Em integrações ERP ↔ Magento 1, é comum coletar preço e estoque de centenas ou milhares de SKUs para conferência, reconciliação ou sincronização periódica. O caminho ingênuo — uma chamada por SKU em catalogProductInfo + outra em cataloginventoryStockItemList — gera 2N requisições, cada uma com seu custo de hidratação de model, round-trip SOAP e parsing XML.
Este módulo expõe um único método SOAP que retorna preço, estoque e dados básicos de catálogo de uma lista arbitrária de SKUs em uma única chamada, lendo direto dos índices catalog_product_index_price e cataloginventory_stock_item via PDO — sem hidratar models Magento.
Este caminho é específico do Magento 1 (sem MSI). Para Magento 2, ver os endpoints REST documentados em Endpoints de API com/sem MSI nesta mesma seção.
2. Convenções e Autenticação
2.1. Convenções
- Endpoint WSDL (SOAP v2):
https://<dominio>/api/v2_soap/?wsdl - Endpoint WSDL (SOAP v1 RPC encoded):
https://<dominio>/api/?wsdl - Login obrigatório: toda chamada ao método exige um
sessionIdobtido previamente vialogin(API_USER, API_KEY). - Numéricos retornados como string —
price,qty,special_pricevêm como string no XML; converter no consumidor (floatval/Decimal).
2.2. Autenticação
ACL exigida
| Item | Valor |
|---|---|
| Resource | mageshop_batchProductInfo |
| ACL | mageshop_batchproductinfo/info/get |
| Nome legível no admin | Batch Product Info → Info → Get Info |
Configuração do role da API
- Admin → System → Web Services → SOAP/XML-RPC - Roles.
- Editar (ou criar) o role que o usuário da API utiliza.
- Em Role Resources, marcar Batch Product Info → Info → Get Info.
- Salvar e vincular ao usuário da API em System → Web Services → SOAP/XML-RPC - Users.
Sem essa ACL marcada, o método retorna fault SOAP código 2 ("Access denied") — independentemente das credenciais estarem corretas.
3. Endpoint — mageshopBatchProductInfoGetInfo
3.1. Identificação
| Campo | Valor |
|---|---|
| Nome do método (SOAP v2) | mageshopBatchProductInfoGetInfo |
| Resource | mageshop_batchProductInfo |
| Alias | batchProductInfo |
| ACL | mageshop_batchproductinfo/info/get |
3.2. Parâmetros
| Parâmetro | Tipo | Obrigatório | Default | Descrição |
|---|---|---|---|---|
sessionId |
string | sim | — | Token retornado pelo login. |
identifiers |
array de string | sim | — | Lista de SKUs ou entity_id. Sem limite explícito de quantidade, ver nota abaixo. |
filterBy |
string | não | sku |
sku ou entity_id. |
store |
string | não | default store view | Store code ou store id. Afeta campos com override por store. |
Notas sobre os parâmetros
identifiers— sem limite declarado pelo módulo. Há dedupe automático (valores repetidos contam uma vez na resposta). A ordem do input é preservada na resposta.filterBy = skubusca pela colunaskuda tabelacatalog_product_entity.filterBy = entity_idbusca pela colunaentity_id.storeafetaprice,status,visibility,special_pricee suas datas — todos campos com override por store no Magento. Se omitido, usa a default store view. Estoque é global no Magento 1 e não depende da store.
Embora o módulo não imponha limite, lotes muito grandes (10k+ SKUs em uma única chamada) podem estourar timeout do PHP-FPM ou limites de tamanho de resposta SOAP. Sweet spot recomendado: Sugestão inicial: 500–2000 SKUs por chamada.
3.3. Exemplo de request — SOAP v1 RPC encoded
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:OpenMage"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soapenv:Header/>
<soapenv:Body>
<urn:mageshopBatchProductInfoGetInfo soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<sessionId xsi:type="xsd:string">{token}</sessionId>
<identifiers xsi:type="urn:mageshopBatchProductInfoIdentifierArray" soapenc:arrayType="xsd:string[3]">
<item xsi:type="xsd:string">SKU-001</item>
<item xsi:type="xsd:string">SKU-002</item>
<item xsi:type="xsd:string">SKU-INEXISTENTE</item>
</identifiers>
<filterBy xsi:type="xsd:string">sku</filterBy>
<store xsi:type="xsd:string"></store>
</urn:mageshopBatchProductInfoGetInfo>
</soapenv:Body>
</soapenv:Envelope>
Variações
Buscando por entity_id:
<identifiers xsi:type="urn:mageshopBatchProductInfoIdentifierArray" soapenc:arrayType="xsd:string[3]">
<item xsi:type="xsd:string">4521</item>
<item xsi:type="xsd:string">4522</item>
<item xsi:type="xsd:string">999999</item>
</identifiers>
<filterBy xsi:type="xsd:string">entity_id</filterBy>
Para store específica:
<store xsi:type="xsd:string">default</store>
4. Resposta
4.1. Exemplo
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:OpenMage"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<ns1:mageshopBatchProductInfoGetInfoResponse>
<result xsi:type="ns1:mageshopBatchProductInfoEntityArray" SOAP-ENC:arrayType="ns1:mageshopBatchProductInfoEntity[3]">
<item xsi:type="ns1:mageshopBatchProductInfoEntity">
<found xsi:type="xsd:int">1</found>
<sku xsi:type="xsd:string">SKU-001</sku>
<product_id xsi:type="xsd:string">4521</product_id>
<type_id xsi:type="xsd:string">simple</type_id>
<status xsi:type="xsd:int">1</status>
<visibility xsi:type="xsd:int">4</visibility>
<price xsi:type="xsd:string">199.9000</price>
<special_price xsi:type="xsd:string">159.9000</special_price>
<special_from_date xsi:type="xsd:string">2026-05-01 00:00:00</special_from_date>
<special_to_date xsi:type="xsd:string">2026-05-31 23:59:59</special_to_date>
<qty xsi:type="xsd:string">42.0000</qty>
<is_in_stock xsi:type="xsd:int">1</is_in_stock>
<manage_stock xsi:type="xsd:int">1</manage_stock>
</item>
<item xsi:type="ns1:mageshopBatchProductInfoEntity">
<found xsi:type="xsd:int">1</found>
<sku xsi:type="xsd:string">SKU-002</sku>
<product_id xsi:type="xsd:string">4522</product_id>
<type_id xsi:type="xsd:string">simple</type_id>
<status xsi:type="xsd:int">1</status>
<visibility xsi:type="xsd:int">4</visibility>
<price xsi:type="xsd:string">89.9000</price>
<qty xsi:type="xsd:string">0.0000</qty>
<is_in_stock xsi:type="xsd:int">0</is_in_stock>
<manage_stock xsi:type="xsd:int">1</manage_stock>
</item>
<item xsi:type="ns1:mageshopBatchProductInfoEntity">
<found xsi:type="xsd:int">0</found>
<sku xsi:type="xsd:string">SKU-INEXISTENTE</sku>
</item>
</result>
</ns1:mageshopBatchProductInfoGetInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
4.2. Campos da resposta
Cada item retornado segue a estrutura abaixo. Campos com valor nulo ou não aplicável podem ser omitidos do XML — o consumidor deve tratar a ausência do nó como "campo não informado".
| Campo | Tipo | Quando vem | Descrição |
|---|---|---|---|
found |
int | sempre | 1 se encontrou o produto, 0 se não. |
sku |
string | sempre | SKU do produto (echo do request quando found=0). |
product_id |
string | found=1 |
entity_id do produto no Magento. |
type_id |
string | found=1 |
simple, configurable, grouped, virtual, bundle, etc. |
status |
int | found=1 |
1 = Enabled, 2 = Disabled. |
visibility |
int | found=1 |
1 = Not Visible, 2 = Catalog, 3 = Search, 4 = Both. |
price |
string | found=1 |
Preço cadastrado do produto (EAV), já com override por store quando aplicável. |
special_price |
string | se houver | Preço promocional cru, mesmo fora da janela special_from_date → special_to_date. |
special_from_date |
string | se houver | Início da promoção (YYYY-MM-DD HH:MM:SS). |
special_to_date |
string | se houver | Fim da promoção. |
qty |
string | found=1 |
Quantidade em estoque. |
is_in_stock |
int | found=1 |
1 em estoque, 0 fora de estoque. |
manage_stock |
int | found=1 |
1 se o estoque é controlado pelo Magento, 0 se não. |
4.3. Pontos importantes
- Ordem da resposta — segue a ordem dos
identifiersno request (depois do dedupe). Isso facilita correlação direta com o pedido sem precisar indexar por SKU no consumidor. - Itens não encontrados — vêm com
found=0e apenasskupreenchido (ouproduct_id, se o filtro eraentity_id). É echo do valor do request, para correlação. Não gera fault SOAP, é resposta normal.
SKUs inexistentes não retornam erro SOAP — retornam um item com found=0 dentro do array de resposta. O consumidor precisa inspecionar o campo found de cada item, não confiar apenas no status HTTP/SOAP.
- Special price cru —
special_pricetraz o valor cadastrado mesmo se a data atual estiver fora do períodospecial_from_date→special_to_date. Cabe ao consumidor decidir se o aplica como ativo ou não, comparando com a data corrente.
O Magento aplica a janela de datas na vitrine, mas a API entrega o valor cru para não impor decisão de negócio ao integrador. Se o ERP quer usar exatamente o preço efetivo do dia, precisa replicar a lógica: se now ∈ [from, to], usar special_price; senão, usar price.
- Estoque global no Magento 1 — não há MSI no M1. Os campos
qty,is_in_stockemanage_stocknão dependem da store informada. O parâmetrostoreafeta apenas preço, status e visibility.
5. Erros — Faults SOAP
| Código | Quando ocorre |
|---|---|
2001 |
filterBy inválido — usar sku ou entity_id (ou os apelidos id / product_id). |
2002 |
identifiers inválido — esperado: array não vazio. |
2003 |
Falha de query no banco. Ver logs do Magento (var/log/system.log / var/log/exception.log). |
5 |
Sessão expirada. Refazer login e tentar novamente. |
2 |
Sem permissão no ACL para o método. Revisar configuração de role descrita em 2.2. |
A diferença entre SKU inexistente e falha de query: SKU inexistente é resposta normal (item com found=0), nunca fault. Fault 2003 é problema de infraestrutura/banco e deve ser escalado ao time de devs com o trecho relevante do log.
6. Receita prática — cliente PHP
$client = new SoapClient('https://sualoja.com.br/api/v2_soap/?wsdl', [
'trace' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
]);
$session = $client->login('API_USER', 'API_KEY');
$result = $client->mageshopBatchProductInfoGetInfo(
$session,
['SKU-001', 'SKU-002', 'SKU-INEXISTENTE'],
'sku',
null
);
foreach ($result as $item) {
if ($item->found) {
echo "{$item->sku}: R\$ {$item->price} | estoque: {$item->qty}\n";
} else {
echo "{$item->sku}: não encontrado\n";
}
}
7. Características técnicas
Para o time de N2 entender por que este endpoint é mais barato que o caminho ingênuo:
- 1 única query SQL com
LEFT JOINem tabelas indexadas (catalog_product_entity,catalog_product_index_price,cataloginventory_stock_item, EAV destatus/visibility/special_price). Mesmo com milhares de SKUs, é 1 round-trip ao banco. - Sem hidratação de model — usa
core_readPDO direto. Não há custo deMage::getModel('catalog/product')->load()por item, que sozinho instanciaria objetos completos e dispararia events. - Preço lido do índice —
catalog_product_index_pricejá contém o preço com regras de catálogo aplicadas no reindex. Não recalcula nada na hora da chamada. - Estoque lido do índice —
cataloginventory_stock_itemdireto. - Sem cache de resposta — preço e estoque mudam com frequência alta; cachear a resposta poderia entregar dado defasado ao ERP. O cache fica por conta do consumidor, com janela curta se for o caso.
8. Boas práticas e resultado esperado
Recomendações
- Use este endpoint sempre que precisar de mais de 1 SKU. Para um único SKU,
catalogProductInfocontinua adequado — mas a partir de ~5 SKUs, este método já compensa pelo overhead reduzido. - Dedupe do lado do cliente é dispensável — o módulo já deduplica
identifiersinternamente. Não precisa pré-processar. - Inspecione
foundpor item — não basta verificar que a chamada retornou sem fault. Cada item pode terfound=0mesmo quando a chamada como um todo deu certo. - Reaproveite o
sessionId— ologinSOAP tem custo. Manter uma sessão viva e renovar só quando vier fault5(sessão expirada) é mais eficiente que logar a cada batch. - Replique a lógica de janela de promoção no ERP —
special_pricevem cru. Se o ERP precisa do preço efetivo do dia, compararnowcomspecial_from_date/special_to_date.
Resultado esperado da adoção
- Redução significativa do número total de chamadas SOAP (de 2N para 1 por lote).
- Menor consumo de CPU e banco de dados na aplicação Magento — uma query única indexada substitui N hidratações de model.
- Sincronizações de catálogo mais rápidas e previsíveis.
- Menor risco de timeouts em ERPs que sincronizam catálogos grandes.
Em caso de dúvidas sobre a implementação ou sobre limites adequados de tamanho de lote para o ambiente, fica à disposição o time de integração.