Automation · Warehouse systems

Automating a system that has no API

The advice for a system with no API is to replace it. That advice assumes you own the system. When the platform belongs to a customer and the contract runs for years, the real question is what you can build against the interface you actually have.

5 concurrent automation sessions
3 cancel-safe restart attempts
2 independent claim guards
Confidential client & operation

Built for a contract-logistics operation running a customer-owned warehouse management platform, where no integration interface was available.

The problem

Several jobs a day were pure data entry against a web interface. Picking an order meant walking a handheld terminal through the same sequence of screens for every single unit, and orders could run to thousands of units. Bulk uploads meant logging into a portal, keying a one-time passcode, and uploading a workbook one sheet at a time. Wave planning meant logging into a third system, running its planner, waiting for it, running its scheduler, waiting again, then filtering a grid and exporting it — a sequence somebody had to stay logged in for.

It was slow, but the real cost was that it was boring. Boring work done by hand produces errors, and errors against live inventory are expensive to unwind.

What we built

A queue-driven automation service that drives the real interfaces the way an experienced operator would, with a bounded pool of concurrent sessions and a job record for every run.

Everything in the design assumes it will fail at the worst possible moment, because eventually it does.

  • Jobs are claimed in the database before they start, so two workers can never pick the same order
  • Jobs stuck mid-run when a server restarts are returned to the queue on boot, with a log line explaining why
  • Cancellation is checked before every step, so stopping a job preserves and reports the partial work already done
  • A stalled session restarts only if nothing was picked yet — never after real work, where a retry would double-count
  • Cases the automation shouldn't handle alone stop and escalate with the specific item, location and reason attached

Failing closed

The most valuable work on this project was unglamorous. An earlier version reported success when uploads had actually failed — the error was raised inside a block that caught and discarded it, so the caller always saw a green result. Rewriting those paths to fail closed, and to treat an unreadable confirmation page as a failure rather than an assumption, mattered more than any speed gain.

One portal returned HTTP 200 on failure, with the real outcome buried in a status field. One vendor template had a spelling error in a column header that the system matched on, so the typo had to be preserved deliberately and documented. Retries wait past the one- time-passcode window, because retrying inside it just re-sends the same rejected code.

Where an ordering decision could cause damage, the safe choice was taken explicitly. Inbound requests are marked handled before any upload runs: a crash mid- upload leaves a visible flag someone can retry, whereas the alternative risks creating duplicate orders in the customer's system. A stuck flag is recoverable. A duplicate order is not.

The result

Work that consumed hours of attention runs from a queue with a full audit trail. More importantly, the failure modes are now visible: when something doesn't work, it says so, in a place someone is looking.

Built with

  • Python
  • Selenium WebDriver
  • SQL Server
  • Thread pools & work queues
  • TOTP
  • openpyxl

On the details we left out

Client, location, system names and volumes are withheld deliberately. We're happy to go deeper on architecture and approach on a call.

Services this draws on

Workload Optimization

Squeeze more throughput out of the hardware and licenses you already pay for.

See the service →

System Integration

Connect aging systems to modern APIs, data platforms, and SaaS tools.

See the service →

More projects

Integration · Inbound logistics

Knowing where the freight actually is

Inbound shipments were tracked by opening carrier websites one tab at a time. We replaced the tabs with live carrier integrations and a workflow that routes exceptions to the person who can fix them.

Read the story →
Planning · Outbound fulfilment

Turning a flat order backlog into a plan the floor can pick

A daily backlog feed said what had been ordered — not what could be built, released or picked. We built the pipeline that turns it into a wave plan, a queued pick order, and a screen that says where each one got to.

Read the story →
Reconciliation · B2B trading partners

Variances that only close when they're actually gone

Two systems held different quantities for the same parts, and the disagreement arrived as a spreadsheet attached to a recurring email. We turned it into a register that remembers — and that nobody is allowed to close by hand.

Read the story →

Got a system like this?

A free assessment gives you a clear picture and a prioritized plan — no commitment.

Book a free assessment