If you run a Magento store and manage your inventory in SmartBill, you already know the problem: a sale happens in the warehouse, stock gets updated in SmartBill, and your online store has no idea. Customers order products that aren’t there. You spend time manually updating quantities. Things fall through the cracks.

This is a solved problem — but the solution isn’t obvious, because SmartBill and Magento don’t talk to each other natively. This post walks through exactly how we built the integration for a Romanian book retailer using n8n, what the tricky parts were, and what you’d need to replicate it.

The setup

The client runs a Magento 2 store and uses SmartBill as their accounting and inventory management platform. When stock levels change in SmartBill — a new delivery arrives, items are written off, a warehouse count is corrected — those changes need to be reflected on the Magento store immediately, or as close to it as possible.

The requirements were straightforward:

  • Stock updates in SmartBill should propagate to Magento automatically
  • Multiple products can change in a single SmartBill event (a delivery might update 13 products at once)
  • The system should handle products that don’t exist in Magento without breaking
  • No manual intervention required once it’s running

Why n8n

We build integrations in n8n rather than Zapier for exactly this type of use case. SmartBill can send a webhook with a batch of products — 13 products in a single payload in this case — and n8n handles the looping, the sequential API calls, and the error handling in a way that’s reliable and maintainable. Zapier would require workarounds for batch processing and gets expensive at volume. n8n runs on our own infrastructure and costs nothing per execution.

How the workflow works

The workflow has five nodes. Here’s what each one does and why.

1. Webhook trigger

SmartBill is configured to POST to an n8n webhook URL whenever stock levels change. The webhook receives a JSON payload containing an array of products — each with a product code (EAN/SKU), product name, warehouse, quantity, and timestamp.

One immediate problem: SmartBill sends the payload as application/x-www-form-urlencoded, not application/json. This means the entire JSON string arrives as the key of the body object rather than as parsed JSON. It’s an unusual pattern that trips up most automation tools.

2. Code node — parsing the payload

Because of the encoding issue above, we can’t just reference $json.body.products directly. The Code node extracts the raw body, takes the first key of the body object (which is the JSON string), parses it, and maps each product into a separate item:

const rawBody = $json.body;
const jsonString = Object.keys(rawBody)[0];
const payload = JSON.parse(jsonString);
return payload.products.map(product => ({ json: product }));

This transforms one webhook event containing 13 products into 13 separate items that the rest of the workflow can process individually.

3. Loop Over Items (SplitInBatches)

The loop node processes each product one at a time. This is important — hitting the Magento API in parallel for 13 products simultaneously can cause race conditions and rate limit issues. Processing sequentially is slower but reliable.

4. Get Details — fetch the current Magento stock item

Before updating stock, we need the internal Magento item_id for the stock record. Magento’s REST API requires this ID in the PUT request URL. We fetch it using:

GET /rest/V1/stockItems/{productCode}

Where productCode is the EAN/SKU from the SmartBill payload. This node is configured with continueErrorOutput — if Magento doesn’t recognise the product code (because the product doesn’t exist in the store), it routes to an error path rather than crashing the whole workflow.

5. Update Stock — write the new quantity to Magento

With the item_id in hand, we make the update:

PUT /rest/V1/products/{productCode}/stockItems/{item_id}

The body sets the new quantity from the SmartBill payload and preserves the existing is_in_stock flag from the GET response. We don’t blindly set is_in_stock: true — if Magento has a product marked out of stock for a reason other than quantity (discontinued, temporarily unavailable), we don’t want the automation to override that.

After the update, the loop moves to the next product until all items in the batch are processed.

The non-obvious parts

The encoding problem. SmartBill’s webhook sends content-type: application/x-www-form-urlencoded but the body is a JSON string. Most webhook handlers expect one or the other. n8n receives the raw body and leaves parsing to you, which is actually an advantage here — the Code node handles it cleanly.

Why you need the GET before the PUT. Magento’s stock update endpoint requires the stock record’s internal item_id, not just the SKU. There’s no way to do a direct update by SKU alone via the standard REST API. So every update is two API calls: one to fetch the current record and extract the item_id, one to write the new quantity.

Preserving is_in_stock. A naive implementation would just send "is_in_stock": true with every update. But in Magento, is_in_stock is a separate flag from quantity. A product with quantity 5 can still be marked is_in_stock: false if someone manually disabled it. We pull the current value from the GET response and send it back unchanged, so the automation only touches quantity.

Error routing on missing products. Not every SKU in SmartBill exists in Magento. If a product is in the warehouse system but hasn’t been listed on the store yet, the GET request returns a 404. The continueErrorOutput setting routes these to a separate path rather than failing the entire batch — the other 12 products in the payload continue processing normally.

What this replaces

Before this integration, someone was manually checking SmartBill for stock changes and updating Magento by hand. For a catalogue of any real size, this is a part-time job that produces errors. The n8n workflow runs automatically on every SmartBill stock event, processes batches of any size, and completes in seconds.

Could you build this yourself?

Yes, if you’re comfortable with n8n and have Magento admin access to generate API tokens. The main things you’d need:

  • A SmartBill account with webhook configuration enabled (available in their API settings)
  • A Magento 2 REST API integration token with catalog inventory permissions
  • An n8n instance (cloud or self-hosted)
  • The Code node logic above to handle the encoding quirk

The workflow itself is about an hour of work once you understand the two-call pattern for Magento stock updates. The parsing problem with SmartBill’s payload encoding is the part most people get stuck on.

If you’re running a Magento store on SmartBill and want this set up properly — with error handling, logging, and monitoring — get in touch.


RemoteMage builds automation and integration systems for ecommerce and operations teams. We work with Magento, n8n, and a wide range of business platforms.

Let's talk

Want to learn more?

Let’s discuss how we can help you to maximize the performance of your ecommerce store and achieve your business goals.

Schedule Your Free Consultation

Privacy Preference Center