Every shipment incurs the same hidden cost: someone reads the tracking number off the
ShipStation screen, finds the matching invoice in QuickBooks, pastes it into the
TrackingNum field, saves the invoice. About 30 seconds per order.
At 50 shipments a day across six storefronts, that's an hour of warehouse time burned on data entry — and a non-trivial error rate. Typos. Wrong invoice. Tracking number that never makes it onto the customer's PDF.
The team knows it's wrong. They don't have time to fix it. So it keeps happening.
"For each ShipStation label, find the matching QuickBooks invoice and write the tracking number on it" is the obvious one-line spec. The implementation runs into three real problems:
ShipStation V2 attaches a numeric external_order_id to each label, but no store_id. With multiple Shopify storefronts feeding one ShipStation account, every lookup is a multi-tenant problem.
QuickBooks invoices are created from Shopify orders by a third-party sync tool. The Shopify order number lands somewhere on the invoice — but where, and in what format?
The QuickBooks API supports a SQL-like query language. PrivateNote is projectable (you can SELECT it) but not queryable (you can't WHERE on it). The obvious bridge field is unusable for direct lookups.
The shipment object — one level above the label in ShipStation's hierarchy — carries a
shipment_number field that's exactly the prefixed Shopify order name:
RB32708 for Raw Blend,
CE5776 for Commercial Equipment,
UK2534 for U-Konserve. The two-letter prefix
unambiguously identifies the source store. No multi-tenant fan-out needed.
For the bridge field, the third-party sync tool writes the prefixed Shopify order name
into the QuickBooks invoice's PrivateNote field exactly. To dodge
the not-queryable problem, each run pages through invoices created in the last 60 days
(MetaData.CreateTime is queryable, so it bounds cleanly) and builds
an in-memory index. For ~900 invoices, it costs ~5 seconds and ~8 paginated queries.
The lookup cascades through three fallback strategies — regular Shopify orders, full
INV-XXXX typed warranty entries, and bare numeric warranty entries — all
caught in the same function.
def find_invoice_for_shipment(shipment_number, by_private_note, by_doc_number):
"""Lookup priority:
1. PrivateNote == shipment_number (regular Shopify orders)
2. DocNumber == shipment_number (warranty: full INV-XXXX typed)
3. DocNumber == "INV-" + shipment_number (warranty: bare number)
"""
matches = by_private_note.get(shipment_number) or []
if matches:
return "private_note", matches
matches = by_doc_number.get(shipment_number) or []
if matches:
return "doc_number", matches
if shipment_number.isdigit():
matches = by_doc_number.get(f"INV-{shipment_number}") or []
if matches:
return "doc_number", matches
return "none", []
An automation scheduled hourly has to survive partial runs, flaky networks, half-finished executions. Three guards make every run safe to repeat with zero side effects:
cache/shipstation/state.json records last_processed_at. Each run pulls labels created since that timestamp, then advances on success.
If invoice.TrackingNum already equals the label's tracking number, skip. No write, no SyncToken churn, no audit-log noise.
If a shipment_number matches more than one invoice (duplicate invoices in QB — it happens), log the conflict and skip. Never risk writing to the wrong one.
The backfill output, end-to-end, on the first real production run against the client's real data:
From that point forward, the warehouse stopped touching tracking numbers. The hourly cron handles every new shipment as it ships. The bookkeeper now trusts that tracking numbers are correct — they always come straight from the source.
A single Python module living inside your automation platform (or as a standalone script). Drops into Windows Task Scheduler or any cron. No SaaS subscription. No vendor lock-in.
Source code, deployment guide, and a runbook — everything your team needs to operate it without a developer in the room.
Onboarding for one storefront from $4,800 + GST. Multi-store builds scoped on the call. Discovery is free; we'll tell you in 30 minutes whether your stack is workable and what the actual cost is.
| Metric | Before | After |
|---|---|---|
| Tracking write source | Human reading ShipStation screen | ShipStation V2 API |
| Time per shipment | ~30 sec manual | 0 sec (automated) |
| Error rate | Typos, wrong invoice | 0% — always from source |
| Run frequency | When staff get to it | Hourly, autonomous |
| Visibility | Nobody knows until a customer complains | Dashboard card · failed runs surfaced |
| Cost over 12 months | ~$15,000 of warehouse time | One-off build + zero recurring |
Every page on this list is drawn from the same Raw Blend build — different problems, same operating model.
One credential surface, one dashboard, one set of automations covering every store. The seventh store is a 30-minute job.
Three feed patterns — scheduled CSV pull, Google Sheet polling, manual Excel upload — handled by one platform.
How to migrate brittle workflows to a custom Python platform without losing the speed advantage you bought no-code for.
OAuth refresh, sparse updates, the PrivateNote-not-queryable gotcha, and how to query invoices reliably at scale.
One URL to bookmark, one-click triggers, one-click log access, zero recurring SaaS. The kind of dashboard staff actually use.
If your shipping volume is anywhere near Raw Blend's, the build pays for itself in the first month. Tell us about your setup — Shopify + ShipStation + QuickBooks is the standard combo we ship against, but other stacks work too.
Discovery is free · Quote in 48 hours · No retainer required