Business System Integration with APIs: Marketplaces, Stock, and Accounting

How to connect marketplaces, stock, and Accurate or Jurnal without staff re-typing data: integration patterns, webhooks versus polling, idempotency, master data and SKU mapping, retries and error queues, daily reconciliation, security, and when n8n or Make is enough.

Published 9 min read
Close-up of network cables plugged into a rack switch

The setup we see most often at online sellers and distributors with 10 to 50 staff goes like this. Orders arrive from Shopee, TikTok Shop, and the website. An admin downloads them twice a day and types them into a stock spreadsheet. Another admin types the same orders into Accurate or Jurnal to make invoices. Every few weeks the warehouse finds that the spreadsheet says 40 units and the shelf holds 12, and somebody has sold stock the company does not have. Fixing this rarely needs a new system. It needs the systems you already pay for to talk to each other reliably, and someone to notice when they stop.

The Real Cost of Re-Typing

Manual re-entry looks cheap because the admins are already on the payroll. Two admins at around UMR spending half their day copying orders add up to one full salary a month, before a single mistake. The mistakes cost more: a wrong SKU on an invoice, a missed cancellation, a return that never went back into stock. Overselling leads to cancelled orders that hurt your store rating, and it peaks during flash sales and before Lebaran, when admins fall furthest behind.

Integration also gives you a log of what moved where, and when. That log settles the argument when finance and the warehouse disagree.

Ways to Connect Systems

Point-to-point means each system calls another directly, for example a script that reads marketplace orders and creates invoices in Jurnal. It is the fastest to build and fine for one or two connections. With five systems you get a tangle where nobody knows which script updates stock. The alternative is a small integration service in the middle that every system talks to, which keeps a record of what has been synced and holds the mapping rules. This is what we build most often, usually a modest Go, Node.js, or Laravel backend with a queue and an admin screen.

Workflow tools (iPaaS) such as Make, Zapier, or n8n let you build flows visually, and n8n can be self-hosted so data stays on your server. A queue (RabbitMQ, a Redis-based queue, or Amazon SQS) is a component more than a pattern: it sits between receiving an event and processing it, so a broken target system delays work instead of losing it. Before any of these, check ready-made omnichannel tools such as Jubelio or Ginee.

PatternGood forWeak pointRough effort
Ready connector or omnichannel toolStandard marketplace, stock, and accounting setupsLimited to what the vendor supportsDays to set up
Point-to-point scriptsOne or two connections at low volumeLogic scattered across scripts, hard to extendDays to a few weeks
Workflow tool (n8n, Make, Zapier)Simple flows and notifications, low to medium volumeComplex branching is hard to test, usage-based pricing on cloud plansHours to days per flow
Integration service (middleware)Several systems, mapping rules, hundreds to thousands of orders a dayYou own and maintain the codeA few weeks to two or three months
Queue between systemsTraffic spikes such as flash sales, slow target APIsOne more component to run and monitorAdded on top of the service

Webhooks, Polling, and Why You Usually Need Both

With polling, your integration asks the other system every few minutes whether anything changed since last time. With webhooks, the other system calls your endpoint when something happens. Webhooks are faster and lighter on rate limits, but they get lost: your server was restarting, or the sender gave up after a few retries. Polling is slower, but you control it.

Our default is both: webhooks for speed, plus a polling sweep every 15 to 60 minutes that fetches anything updated in the last few hours and fills the gaps. Each marketplace runs its own partner programme with its own app registration, permission scopes, and event types, and they change over time. Tokopedia's seller integrations, for instance, now sit under TikTok Shop. Read the current documentation for your own account before designing anything, rather than relying on a blog post, this one included.

Duplicates and Idempotency

Every integration receives the same event twice sooner or later. A webhook is resent because your reply was slow, a polling sweep picks up an order the webhook already delivered, or someone re-runs a failed job. If that creates two invoices or deducts stock twice, your numbers drift every week and nobody knows why.

The fix is idempotency, meaning that processing the same event again has no extra effect. In practice, store every external ID you have handled (marketplace order number, event ID) under a unique constraint in your database, and check it before creating anything in the target system. Put the marketplace order number on the invoice as a reference, so you can search for it before creating a new one. Status works the same way: a cancelled order must not move back to paid because an old event arrived late.

Decide Which System Owns What

Before writing any code, write down which system is the source of truth for each kind of data. Two systems that both believe they own stock will overwrite each other forever.

  • Stock: usually the inventory or warehouse system. Marketplaces receive stock levels and never send them back.
  • Prices: often the ERP or a price list kept by sales, pushed out to each channel, while promotions set inside the marketplace are left alone.
  • Customers: marketplace buyers are usually booked as one customer per channel in accounting. Buyer details are often masked by the platform anyway, and UU PDP is a good reason not to copy personal data you do not need. B2B customers belong in the accounting or CRM system.
  • Products: one master list, with every channel's product and variant IDs mapped to it.

SKU mapping is where most of the effort hides. The same coffee is KOPI-250 in the warehouse, has three variant IDs on Shopee, and appears on TikTok Shop inside a bundle of two. Units add another layer: you buy by the carton of 24, store by the pack, and sell by the piece. Keep a mapping table with conversion factors in the integration service, give an admin a screen to maintain it, and stop the sync for any unmapped SKU instead of guessing.

Rate Limits, Retries, and an Error Queue Someone Watches

Every API limits calls per second or per day, and the limits differ per platform and sometimes per plan. Hitting one returns an HTTP 429 or a platform error code. Retry with exponential backoff (wait 1 second, then 2, 4, 8, with a little randomness), and batch where the API allows, for example sending stock for many SKUs in one call instead of one call each.

Some errors do not go away with a retry: an unmapped SKU, a closed accounting period, a product deleted in one system but not the other. Those belong in an error queue, a table with the payload, the error message, and a retry button. This is the part most often skipped, and it decides whether the integration still works in month six. Someone has to look at that queue every day, and an alert on Telegram, Slack, or email when it grows past a threshold makes sure they do.

Add a daily reconciliation report. Compare yesterday's orders per channel with the invoices in Accurate or Jurnal, and stock per SKU in the warehouse system with what each marketplace shows. Most days it shows zero differences. On the day it does not, you hear about it from a report instead of from a customer.

An integration without an error queue and a person watching it is just a faster way to produce wrong data.

Security for Keys and Endpoints

API keys and OAuth tokens give full access to your store and your books. Keep them in environment variables or a secret manager on the server, never in source code, a shared spreadsheet, or a WhatsApp group. Give each integration its own credentials with the narrowest permissions the platform offers, so you can revoke one without breaking the rest, and rotate them when someone with access leaves.

On webhook endpoints, verify the signature the sender includes and reject anything that fails. Where your accounting system or ERP supports it, restrict API access to the fixed IP address of your integration server. Log what was synced, but leave out customer addresses and phone numbers you do not need.

When n8n or Make Is Enough

Our honest view is that many small businesses do not need a custom integration at all. If an omnichannel tool already connects your marketplaces, stock, and accounting product, use it and spend the money elsewhere. If you have one or two flows, a few hundred orders a day, and someone on the team who is comfortable with logic, n8n or Make will do the job for a small monthly cost.

It stops being enough when the logic grows: bundles and unit conversions, partial shipments, returns that must put stock back and create credit notes, or hundreds of mapping rules. A visual flow with dozens of branches is hard to test and harder to hand over to the next person, and cloud plans that charge per operation get expensive at high volume. That is usually the point to move the core logic into a small integration service and keep n8n for the simple notifications around it.

Where to Start

  1. 1Draw the current flow on one page: every system, every spreadsheet, and every person who copies data from one to another, with daily volumes.
  2. 2Pick the flow that hurts most, usually marketplace orders into stock, and integrate that one first.
  3. 3Write the ownership table: which system owns stock, prices, products, and customers.
  4. 4Build the SKU and unit mapping, and merge products that exist under several names.
  5. 5Check API access for every system: if your plan includes it, how to register an app, and what the rate limits are.
  6. 6Build idempotency, retries, the error queue, and alerts from the first version, not after the first incident.
  7. 7Run alongside manual entry for two to four weeks, compare against the daily reconciliation report, and only then switch the old process off.

We build integration services of this kind, usually small, with a queue, an error screen for the admin team, and a reconciliation report, and we hand over the code and documentation at the end. When a ready connector or an n8n flow is enough, we will tell you so.

Key takeaways

  • Re-typing orders between marketplaces, stock, and accounting costs a salary a month plus the errors, and the errors cost more.
  • Use webhooks for speed and a regular polling sweep to catch what the webhooks missed.
  • Make every handler idempotent and decide in writing which system owns stock, prices, products, and customers.
  • Unmapped SKUs and failed calls belong in an error queue with alerts, checked daily, plus a daily reconciliation report.
  • Ready connectors, n8n, or Make are enough for simple flows. Move to a small integration service when bundles, units, and returns make the logic complex.
Share this article

Related articles

More articles on software development, AI, cloud, and infrastructure.

Laptop showing server code next to a terminal window on a deskBackend Development

9 min read

Go vs Node.js for Backend Services: An Honest Comparison

How Go and Node.js really differ for backend work: memory and throughput, goroutines versus the event loop, Go types versus TypeScript, hiring in Indonesia, deployment size, and how to decide which one a service should use.

Code on two monitors seen through a pair of glassesBackend Development

10 min read

Go Concurrency in Practice: Goroutines, Channels, and Context

How to use goroutines without leaking them, when to pick a channel or a mutex, how context carries cancellation through a request, worker pools with errgroup, and the race detector habits that keep concurrent Go code correct.

Let’s talk

Looking for a software development partner?

Tell us about your project, what you need to build, and the challenges you are facing. We can discuss the technical approach, scope, timeline, and estimated cost.

Start a conversation