Notes / February 6, 2026

Laravel, ShipStation, and shipping reconciliation (schools & pallets)

When tracking alone is not enough: verifying shipments against institutional rules and physical pallets.

Anonymized B2B logistics case: schools, manifests, and pallets—not consumer doorstep delivery.

The merchant already had ShipStation for labels and tracking. The pain was operational truth: finance and warehouse leadership could not answer, from systems alone:

  • “Is this carton on the approved manifest for Institution X?”
  • “Did Pallet 14 actually contain every order assigned to it before the truck departed?”
  • “Why does ERP revenue not match delivered cartons this month?”

We put Laravel in the middle—not to replace ShipStation, but to normalize events, apply business rules, and expose reconciliation dashboards exports.


1. Ingestion: webhooks first-class

Routes

  • POST /webhooks/shipstation behind signature verification (ShipStation’s shared secret pattern).
  • Return 200 fast; push payload to queue—never do heavy SQL in HTTP thread.

Idempotency

  • Table webhook_events: unique (provider, event_id) or hash of body + type.
  • Handlers must tolerate at-least-once delivery—insertOrIgnore + state machine transitions.

Event types we cared about

  • SHIP_NOTIFY — tracking number exists
  • ITEM_ORDER_NOTIFY — line-level ship quantities (when available)
  • Fulfillment updates that implied multi-carton splits

2. Normalization layer

ShipStation’s orderNumber often maps to merchant internal order—sometimes with prefixes (PO-12345-B). We built:

  • Regex rules per client (versioned YAML) to extract internal_order_id, line_suffix, manifest_id from tags/notes when orderNumber was ambiguous.
  • Dead letter queue for payloads that fail normalization with raw JSON attached for human triage.

3. Institutional verification (“school” rules)

Table ship_to_approvals (illustrative):

  • institution_id, ship_to_hash (normalized address), valid_from, valid_to, status
  • Queue worker: on each outbound ship event, verify order’s ship-to matches an active approval for the SKU category (some institutions only accept certain product lines).

Outcomes

  • MATCHED, FLAGGED, BLOCKED (blocked triggers Slack + holds ERP export line).

4. Palletization

Schema

  • pallets (id, truck_load_id, status open|sealed|departed)
  • pallet_items (pallet_id, carton_id or order_line_shipment_id, scanned_by, scanned_at)
  • Scan API from warehouse handhelds: Laravel Sanctum tokens, optimistic locking on pallet status (sealed rejects new scans).

Reconciliation

  • Nightly job: assigned_to_pallet vs scan_events vs ShipStation quantity_shipped.

5. Dashboards and exports

  • Ops UI: filters by institution, pallet, date range; drill to raw webhook JSON.
  • Finance CSV: vocabulary matched their existing “GL export” column names—adoption hinge.
  • Audit trail: who overrode a mismatch and why (override_reason required).

6. Why not do this inside ShipStation alone?

ShipStation excels at carrier workflows—not arbitrary institutional policy graphs or ERP reconciliation state. Laravel gives:

  • Policies (Gate) for roles (warehouse vs supervisor vs read-only finance)
  • Horizon for queue visibility
  • Fast iteration on rules without carrier downtime

7. Failure stories we planned for

  • Webhook storm on Cyber Monday → scale workers horizontally; DB connection pooling tuned.
  • Institution changes address mid-season → approvals versioned; old shipments remain tied to old hash.

Resume framing

“Built a Laravel reconciliation hub on ShipStation: signed webhooks, idempotent normalization, institutional rule engine, pallet scan model, and finance-grade exports.”