Todo lojista já perdeu venda por produto que acabou sem ninguém perceber. E todo lojista já foi orientado a olhar o relatório em Reports > Products > Low Stock, que é uma tela ótima e que ninguém abre.
O jeito que funciona é o contrário: a informação vai até a pessoa. O Magento já expõe esse dado por API desde o 2.0, o n8n conecta em cinco minutos e o WhatsApp é onde o dono da loja realmente lê.
O endpoint que já existe
No etc/webapi.xml do módulo CatalogInventory está declarada esta rota:
<route url="/V1/stockItems/lowStock/" method="GET">
<service class="Magento\CatalogInventory\Api\StockRegistryInterface"
method="getLowStockItems"/>
<resources>
<resource ref="Magento_Catalog::catalog_inventory"/>
</resources>
</route>O método por trás é getLowStockItems($scopeId, $qty, $currentPage = 1, $pageSize = 0), e o filtro que ele monta é literalmente qty <= $qty. Teste antes de montar fluxo nenhum:
curl -s -H "Authorization: Bearer SEU_TOKEN" \
"https://sualoja.com.br/rest/V1/stockItems/lowStock/?scopeId=0&qty=5¤tPage=1&pageSize=50"Sobre os parâmetros: o scopeId é o website, e o padrão do core é 0 — a coluna website_id da tabela cataloginventory_stock_item nasce com esse valor. O qty é o corte que você define, e é aí que esse endpoint difere do relatório do admin, que usa o Notify for Quantity Below de cada produto.
O token sai de uma Integration em System > Extensions > Integrations. Na aba de API, marque só Catalog > Inventory, que é o recurso Magento_Catalog::catalog_inventory exigido pela rota. Não dê acesso a mais nada.
Os três nodes do n8n
1. Schedule Trigger. Trigger Interval em Days, Days Between Triggers em 1, Trigger at Hour em 8 e Trigger at Minute em 0. Quem prefere cron escreve 0 8 * * * na opção Custom (Cron). A documentação do n8n avisa o que quase todo mundo esquece na primeira vez: salve e publique o workflow, senão o agendamento não roda.
2. HTTP Request. Method GET, URL igual à do curl acima. Em Authentication use Generic Credential Type > Header Auth, com o nome do header em Authorization e o valor em Bearer SEU_TOKEN. Ponha os parâmetros em Query Parameters, um a um, em vez de colar tudo na URL — fica mais fácil de mudar o corte depois.
3. WhatsApp Business Cloud. Resource Message, operation Send Template. E aqui vem a parte que não é escolha sua: mensagem que a empresa inicia, fora de uma conversa já aberta pelo cliente, só sai como template aprovado. Está escrito na documentação do próprio WhatsApp. Crie um template de categoria Utility no Business Manager, com uma variável para o número de produtos, e espere a aprovação antes de testar.
Se você quiser evitar mensagem inútil nos dias em que está tudo certo, ponha um node If entre o HTTP Request e o WhatsApp, testando se a lista voltou vazia. É um node a mais e economiza uma notificação por dia.
Três detalhes antes de subir isso
A resposta não traz o SKU. Esse é o tropeço número um. A StockItemInterface tem item_id, product_id, qty, is_in_stock e mais uma pilha de flags de configuração — mas não tem sku. Se você quiser o código do produto na mensagem, precisa de uma segunda chamada, em /rest/V1/products, buscando por entity_id. Para o alerta diário eu nem faço isso: mando a quantidade de itens e o link do relatório do admin.
Esse é o estoque legado, não a Salable Quantity. O endpoint lê a tabela cataloginventory_stock_item. Se a sua loja usa múltiplas fontes de estoque do MSI, o número que sai daqui pode não ser o mesmo que aparece na coluna Salable Quantity do grid de produtos, que é calculada com reservas e fontes. Em loja de fonte única, que é a maioria por aqui, bate.
Cuidado com o volume. Se você puser qty=10 num catálogo de 20 mil SKUs, é bem capaz de voltar meio catálogo, porque produto desativado e produto que nunca foi vendido também entram na conta. Comece com qty=3, olhe o tamanho da lista e vá subindo. E deixe o pageSize sempre preenchido: sem ele, o padrão do método é 0.
Uma observação de custo, que vale para qualquer alerta por WhatsApp: template de categoria Utility entregue dentro de uma janela de atendimento aberta é gratuito, mas o alerta diário quase sempre cai fora dessa janela e é cobrado por mensagem. Uma mensagem por dia é barato. Uma por SKU não é.
Perguntas rápidas
O que é o scopeId dessa chamada?
É o website do item de estoque. O core trata 0 como escopo padrão e a coluna website_id da tabela cataloginventory_stock_item nasce com esse valor, então scopeId=0 é o que funciona na esmagadora maioria das lojas.
Dá para receber o alerta no Telegram ou no e-mail em vez do WhatsApp?
Dá, e é bem mais simples. Telegram e e-mail não têm janela de 24 horas nem template para aprovar. Você troca só o terceiro node do fluxo e o resto continua igual.
Preciso deixar o n8n no mesmo servidor da loja?
Não. Ele conversa com a loja por HTTPS como qualquer outro cliente de API. Só garanta que o token fique guardado como credencial do n8n e não escrito dentro do node de HTTP Request.
Pra conferir na fonte
- Magento_CatalogInventory etc/webapi.xml — GitHub
- Schedule Trigger node — n8n Docs
- WhatsApp Business Cloud node — n8n Docs
- Pricing on the WhatsApp Business Platform — Meta for Developers