If you sell the same SKUs on TikTok Shop and somewhere else, the number that ruins your week is the one that went to zero everywhere except TikTok Shop. The fix is a small n8n workflow that treats one system as the real stock count, reads it on a schedule, and pushes only the changed quantities to TikTok Shop, minus a safety buffer, with an alert when something looks wrong. This guide is the build-it-yourself version of that pattern. It is about inventory and stock levels, not the order lifecycle, so if you also need to process incoming orders, that is a separate job covered in how to automate TikTok Shop order processing with n8n.
I have built this exact sync against the TikTok Shop API, so most of what follows is the shape of a workflow I trust rather than theory. Where the TikTok side is genuinely fuzzy (their endpoints and field names move between API versions), I will tell you to confirm against the current docs instead of quoting a path I am not certain of today.
Quick answer
- One source of truth. Shopify, WooCommerce, or a Google Sheet owns the real stock number. TikTok Shop is a follower, never a co-owner.
- Schedule Trigger, not guesswork. A Schedule node every 5 to 15 minutes reads current stock and drives the sync. Add webhooks on top only if your source emits them.
- Diff before you push. Compare source stock to what TikTok Shop shows and update only the SKUs that actually changed. Blind full pushes burn your rate limit.
- Subtract a buffer. Publish quantity minus a small safety buffer so the last unit cannot sell twice during the sync gap.
- Alert on low stock and on failure. A Telegram or Slack message when a SKU goes thin, and an Error Trigger when a push fails, so nothing breaks quietly.
Why does TikTok Shop stock drift out of sync?
Stock drifts because two channels are both selling from the same shelf but each keeps its own count. A unit sells on your Shopify store, Shopify decrements, and TikTok Shop still shows it as available until something tells it otherwise. If nothing does, a TikTok buyer orders a unit you already shipped from another channel, and now you are canceling an order and eating a metric hit on a marketplace that punishes cancellations hard.
The other cause is manual updates. Someone edits a quantity in a spreadsheet, forgets TikTok Shop exists, and the gap opens. Automation removes the someone forgot failure mode entirely, which is most of the value. You are not trying to be clever, you are trying to make the boring update happen every few minutes without a human in the loop.
What is the reliable n8n pattern for inventory sync?
Every dependable version of this workflow is the same five stages. Learn the shape once and the specific tools slot in.
| Step | Node | Role |
|---|---|---|
| Trigger | Schedule Trigger (or Webhook) | Starts the sync on a clock, or reacts to a stock-change event |
| Read | HTTP Request / Shopify / Google Sheets | Pulls current quantities from the source of truth |
| Diff | Code node | Compares source stock to TikTok Shop, keeps only changed SKUs |
| Push | HTTP Request | Signs and sends the inventory update to the TikTok Shop API |
| Alert + log | Telegram / Slack + Sheets or DB | Flags low stock and failures, records what changed |
The reason this order matters: the diff stage is what keeps you inside the API rate limits and makes failures readable. If you skip it and push all SKUs every cycle, you cannot tell a real change from noise, and you will hit throttling on any real catalog. Read, diff, then push.
Which system should own the stock number?
Pick one, and be strict about it. The right owner is whatever system already decrements stock when fulfillment happens, because that number is closest to physical reality.
| Source of truth | Read stock with | Best when |
|---|---|---|
| Shopify | Shopify node or Admin API, plus inventory webhooks | Shopify is already your primary storefront |
| WooCommerce | HTTP Request to the WooCommerce REST API | WordPress runs your main store |
| Google Sheet | Google Sheets node | Small catalog, or a warehouse that lives in a sheet |
| Warehouse / ERP | HTTP Request to its API | Fulfillment truth lives outside any storefront |
The failure mode to avoid is two systems both believing they own the number. If Shopify and a spreadsheet both write stock, they will disagree, and TikTok Shop inherits whichever wrote last. One owner, everything else follows.
How do I connect n8n to the TikTok Shop API?
The stable architecture, the part that does not change much between API versions, looks like this:
- Register an app in the TikTok Shop Partner Center. This gives you an app key and app secret.
- Complete the OAuth flow for the specific shop you manage, which returns an access token (and a refresh token) scoped to that shop.
- Sign each API request. TikTok Shop calls are signed requests, so you compute a signature from your parameters and secret and attach it along with the token and a timestamp.
- Call the product and inventory endpoints to read and update the available quantity for a SKU.
I am deliberately not pasting specific endpoint URLs, field names, or permission scopes here. TikTok Shop revs its API versions and moves routes, and a path I paste today may be wrong by the time you read this. Open the current Partner Center API reference, find the inventory update endpoint for your API version, and confirm the field names there. What is stable is the flow above: registered app, per-shop OAuth token, signed requests to inventory endpoints.
On the n8n side you can be fully concrete. Use an HTTP Request node for the signed calls, store the app secret and token in n8n credentials rather than in the workflow, and put the signing logic in a Code node so you compute the signature once and reuse it. If token refresh trips you up or the workflow simply will not fire, the usual culprits are an expired token, a signing string built from the wrong parameters, or a trigger that was never activated.
How do I diff stock so I only push what changed?
This is the heart of the workflow. You have current source quantities on one side and current TikTok Shop quantities on the other, and you want a short list of SKUs where they disagree, adjusted for your safety buffer. A Code node does it cleanly:
// Inputs:
// items[0].json.source -> [{ sku, qty }] from your source of truth
// items[0].json.tiktok -> [{ tiktok_sku_id, qty }] from TikTok Shop
// items[0].json.map -> { internal_sku: tiktok_sku_id }
const SAFETY_BUFFER = 2; // never publish the last units
const LOW_STOCK = 5; // flag thin SKUs
const source = items[0].json.source;
const tiktok = Object.fromEntries(
items[0].json.tiktok.map(t => [t.tiktok_sku_id, t.qty])
);
const map = items[0].json.map;
const updates = [];
const lowStock = [];
for (const row of source) {
const tiktokId = map[row.sku];
if (!tiktokId) continue; // unmapped SKU, skip and log separately
const target = Math.max(0, row.qty - SAFETY_BUFFER);
const current = tiktok[tiktokId];
if (current !== target) {
updates.push({ json: { tiktok_sku_id: tiktokId, qty: target } });
}
if (target <= LOW_STOCK) {
lowStock.push({ sku: row.sku, qty: target });
}
}
// Attach low-stock list so a later node can alert on it
return updates.length
? updates.map(u => ({ json: { ...u.json, _lowStock: lowStock } }))
: [{ json: { noChanges: true, _lowStock: lowStock } }];Two things earn their keep here. The SAFETY_BUFFER means TikTok Shop never advertises the final unit, so a buyer cannot grab it in the seconds between your sync and another channel sale. The unmapped-SKU skip stops you from silently pushing stock to the wrong variant. Everything downstream operates on a small, honest list of real changes.
How do I push the update to TikTok Shop?
Feed the diff output into an HTTP Request node, one call per changed SKU (or a batch call if the current API version supports it, which is worth checking). The request is a signed call to the inventory update endpoint. Conceptually the body carries the shop SKU ID and the new available quantity, something along these lines:
{
"sku_id": "TIKTOK_SKU_ID",
"available_stock": [
{ "warehouse_id": "YOUR_WAREHOUSE_ID", "quantity": 18 }
]
}Treat that payload as illustrative, not gospel. The exact field names (available_stock, warehouse_id, and friends) depend on your API version, so confirm them in the Partner Center reference before you wire it up. The n8n mechanics do not change: set the HTTP Request method and URL per the docs, add the token, timestamp, and computed signature as the docs require, and enable Retry On Fail on the node so a transient 5xx does not drop a real stock change.
How do I get alerted before I oversell?
Alerting is the difference between a sync you trust and one you babysit. You want two independent signals.
Low-stock alerts come from the _lowStock list the Code node produced. Route it into a Telegram or Slack node so thin SKUs get a human decision: restock, pause the listing, or let it ride. This is proactive, it fires before a stockout, not after.
Failure alerts come from the n8n Error Trigger. Build one small workflow that starts with an Error Trigger and ends in a Telegram message, then set it as the Error Workflow for your sync. Now a failed push pings you with the workflow name and the failing node instead of leaving TikTok Shop showing a number you never confirmed landed. A minimal alert body:
{
"chat_id": "YOUR_CHAT_ID",
"text": "Inventory sync failed in \"{{$json.workflow.name}}\" at node \"{{$json.execution.lastNodeExecuted}}\": {{$json.execution.error.message}}"
}The pairing matters. Low-stock alerts stop you from selling stock you do not have; failure alerts stop you from trusting a sync that quietly broke. Telegram and Google Sheets are the two tools I reach for most for this, because the log doubles as an audit trail when a buyer disputes availability.
How often should the sync run, and what about reconciliation?
For the main loop, a Schedule Trigger every 5 to 15 minutes fits most stores. Sell fast on a few SKUs? Tighten those or drive them from a webhook. Sell slowly? A longer cycle is fine and kinder to the API. Match the interval to real sales velocity, not to a number that sounds impressive.
Separately, run a daily full reconciliation. The incremental diff can drift over weeks (a missed webhook, a manual edit, an API blip), so once a day read every SKU from both sides, log any mismatch, and correct it. Think of the frequent sync as keeping pace and the daily pass as catching anything the fast loop missed. The reconciliation run is also where a good log pays off: you can see exactly which SKUs drifted and start asking why.
When is n8n the wrong tool for this?
Honesty first. If a purpose-built multichannel inventory platform already syncs TikTok Shop out of the box and you are happy paying for it, do not rebuild it in n8n for its own sake. n8n wins when your source of truth is custom, when you need logic those platforms do not offer (buffers per SKU, tiered alerts, warehouse-specific quantities), or when you already run self-hosted n8n and want to own the flow without another subscription. For a plain Shopify to TikTok sync with no special rules, weigh a ready-made connector first.
Want this built and maintained for you?
You can assemble all of this yourself over a weekend if this is your kind of work. If you would rather have a stock sync that just runs, the done-for-you TikTok Shop automation service is exactly that: inventory sync with safety buffers, low-stock and failure alerts, and a reconciliation pass, built on self-hosted n8n and handed over documented. It is the same reliability approach behind the hands-free TikTok Shop order processing and inventory sync I built as a real project, where a failed update alerted a human on Telegram instead of stalling silently. A free discovery call turns into a fixed price within 48 hours, and the first week is refundable.
Tags
Frequently asked questions
How do I sync TikTok Shop inventory with n8n?
Run a scheduled n8n workflow that reads current stock from your source of truth (Shopify, WooCommerce, or a sheet), compares it to what TikTok Shop currently shows, and pushes an update only for the SKUs that changed. Add an alert step so a failed push or a low-stock item pings you instead of failing silently.
Can I sync TikTok Shop stock in real time?
Not truly instant, but close. If your source of truth emits webhooks on stock changes (Shopify does), n8n can react in seconds; otherwise a schedule every few minutes is the practical floor. For overselling protection, a tight schedule plus a safety buffer is more reliable than chasing true real-time.
Which system should be the source of truth for inventory?
Pick one system that owns the real number, usually the store or warehouse tool that already processes fulfillment, and treat every other channel including TikTok Shop as a follower. Two systems both claiming to own stock is the root cause of most overselling.
How do I stop overselling across TikTok Shop and my other channels?
Subtract a safety buffer from the real quantity before you publish it to each channel, so no single channel can sell the last unit twice during the sync gap. Combine that with a short sync interval and a low-stock alert so thin SKUs get human attention.
Does the TikTok Shop API let me update stock directly?
Yes. TikTok Shop exposes product and inventory endpoints that let you update the available quantity for a SKU on an authorized shop. Confirm the exact current paths and field names in the TikTok Shop Partner Center docs, because the API versions and routes change over time.
How often should the inventory sync run?
Every 5 to 15 minutes covers most stores without hammering the API. High-velocity SKUs justify a tighter interval or a webhook-driven push; slow movers are fine on a longer cycle. Match the frequency to how fast you actually sell, not to a number that feels impressive.
Need something like this built?
Free 15-min discovery call. I'll listen, ask honest questions, and tell you if I can help.