Skip to main content

What’s new at Endless

Changelog

The latest features, improvements, and fixes across Endless Commerce.

fix

Get Shipment: Manual Repair Records Line Items

The Get shipment action, used to re-record a shipment from the warehouse when the periodic poll missed one, used to record the shipment with no line items and mark the fulfillment fulfilled outright. That left a repaired shipment indistinguishable at a glance from one the poll recorded properly — the record read as complete on the fulfillment, but what actually shipped could not be seen on it.

The action now records the same shipment shape as the poll, with the line items on the shipment, and lets the fulfillment’s state follow from what was covered. A partial shipment repaired by hand leaves the fulfillment in progress instead of forcing it to fulfilled, so a partial repair reads correctly on the order.

Applies to newer sales orders. Older sales orders are unchanged.

improvement

Order Item Changes On The Timeline

Adding, removing, or updating an item on an order now records a before-and-after entry on the order timeline. Both bulk edits and single-line edits are covered, and each entry names the item, the fields that changed, and the values on each side, so the timeline explains what changed without opening the item. The existing backfill task for older item edits picks up the same format.

improvement

ShipStation: Full Error Response On The Timeline

When ShipStation refuses a new order, the timeline entry for the failure now carries the full response from ShipStation under the More details row, alongside the short error message. The visible line stays concise, and the underlying reason — which used to be discarded, leaving customers with only “no orderId returned” — is there when you need to see it.

fix

Extensiv: Partial Shipments Recorded, Stuck Fulfillments Cleared

Extensiv fulfillments used to be marked as fully shipped the moment Extensiv returned a tracking number, so a partially shipped order looked complete in Endless and was reported complete to any downstream sales channel. Endless now records what each Extensiv package actually contained as a shipment on the fulfillment, and the fulfillment stays in progress until every item has shipped. Inventory is committed once every item has shipped rather than on the first tracking number, packages without a tracking number are recorded rather than dropped, and re-polling a fulfillment without changes leaves it alone, so the 15-minute Extensiv poll no longer duplicates shipment activity over its 24-hour visibility window. Miscounted orders can be repaired one fulfillment at a time; orders already reported complete to Shopify cannot be corrected there, since Shopify does not accept shrinking an existing fulfillment.

Extensiv sometimes leaves the SKU off a package content and names the line through its own order item id instead. Endless resolved contents by SKU alone, so those contents matched nothing and no shipment was recorded — the fulfillment stayed in progress after the order shipped, with nothing on the log to say so. A package content now falls back to the Extensiv order item id to find the matching line, where the SKU is reliably present. A content that still cannot be resolved is reported on the fulfillment’s log with its Extensiv line rather than dropped, so a mismatch shows up on the order. A background sweep re-ingests already-stuck fulfillments once the fix is deployed. It checks each candidate against Extensiv’s API, only touches orders that report shipped quantities, paces its calls against Extensiv’s rate limit, and reports throttled orders so the next run picks them up.

feature

EDI Fulfillments: Real GS1 Carton Labels

Generate Labels on a fulfillment’s Containers tab now produces real scannable GS1-128 carton labels for retailers with a GS1 label mapping. What the button rendered before looked like a carton label and carried no barcode symbology, so a carton sent against it was refused at the retailer’s dock. Labels are requested once per non-archived container on the fulfillment, ordered so the carton number on the label matches the “Container N” shown in the packer’s tab. Fulfillments with no retailer label mapping keep the local label they always used, so nothing changes for anything outside EDI.

Before a batch is sent, cartons without a valid GS1 SSCC are refused and the missing codes become the primary action, so an operator gets a fix rather than a disabled button. When a retailer expects GS1 labels but the account is not set up to generate them, the action blocks and explains rather than substituting a local label the retailer would reject. Once labels exist the menu item reads Regenerate Labels.

feature

Working Imported Orders Without Claiming Authority

The Claim Authority and Reset Order controls are gone from imported orders. You can edit sales-order details, add and change fulfillments, and cancel the order without first taking authority away from its source integration. Fields the source integration manages carry a caution and a save-time confirmation on the fields that use them, so an edit that the source may later overwrite goes through with a warning rather than as if nothing had changed. The fulfillment plan follows the source until a fulfillment change is made in Endless or work begins on it; from that point Endless drives the plan and the activity timeline records the handoff. Canceling an in-progress order cancels every unfulfilled fulfillment order under it, preserves shipments that already went out, and stops the source from restoring the plan on its next pass.

Sales and fulfillment order details are reshaped around the new default. Internal notes live on their own Notes tab with a count badge, and the tab you had open stays selected as you move next or previous through the orders list. The two separate banners at the top of an imported order — one for source-managed ownership, one for fulfillment sync — collapse into a single sync card that names the source, whether it is still sending updates, and whether the fulfillment orders match what the source said. Fulfillment cards default to expanded on active fulfillments and collapse to their items list once fulfilled or cancelled. Advanced view splits an active fulfillment across tabs for Items, Details, Metadata, Timeline, Shipment, and Containers; simple view shows items only. Blockers on a fulfillment list every unmet condition rather than only the next one, with a per-condition Resolve button next to each. The sync card no longer overloads the word “blocked”, and the copy on bulk Reload from source, refresh toasts, and the timeline explains changes in terms of fulfillment orders rather than an internal fulfillment plan.

Shopify keeps sending updates and shipments back after a local change. A Shopify order used to stop accepting webhook updates the moment an Endless user claimed it to route a fulfillment somewhere — cancellations, quantity changes, and other source-side edits were rejected without a trace on the order, and only surfaced later when the mismatch was investigated. Routing a fulfillment no longer takes ownership of the order itself. Shopify keeps sending order-level updates and Endless keeps applying them, while the routed WMS remains the one that reports the shipment. A refused webhook update now shows on the order timeline instead of disappearing, so a rejection is visible where the update would have landed. Canceling an order also refuses up front when one of its fulfillments cannot be modified by the person acting, rather than partially applying and leaving the order in a mixed state. Separately, a Shopify-owned order shipping from a building that had a Default WMS attached was failing to close through Shopify — the warehouse default was being treated as if the order had already been re-routed away from Shopify, and the ship confirmation was rejected on the way back in. Shopify now keeps the fulfillment until you re-route it explicitly or hand it off to a downstream system, so the close-and-ship flow completes even when the building has a Default WMS set; explicit re-routes still transfer control right away.

improvement

Carriers: Royal Mail Added

Royal Mail is now selectable as a carrier alongside the rest of the built-in carrier list. Pick it from the carrier picker anywhere a carrier is set.

feature

Retail EDI: Split Orders And Pack Cartons By Store

A retail EDI purchase order that names a per-store breakdown now splits into fulfillments that carry that plan, and the containers tab knows how to pack against it. Auto-Pack gains a By store (retailer plan) strategy — one container per destination store, pre-filled to the retailer’s quantities, selected by default when the fulfillment carries a store distribution. Before anything is generated it lists shortfalls, identifiers it could not resolve, and units the retailer named no store for. Non-EDI orders and retailers that ship to one destination see no change — the strategy, warnings, validator option, and pick list export all depend on the distribution being present.

Every carton carries its mark-for store as a badge, and a Store column appears on the summary tab. Contents flagged against the retailer’s plan — “Store 0204 expects 25 units”, “Not on store 0201’s plan” — sit on the specific item row that caused them, and the checks aggregate across a store’s cartons so a surplus on one SKU does not offset a shortfall on another. The Validate Containers dialog gains a Pack for Store Quantity option that requires every store’s cartons to match the plan before Close Containers is allowed; the option turns itself off on fulfillments without a distribution and never persists true. Export Store Pick List (DC, Store, SKU, UPC, Product Name, Quantity) is offered whenever a fulfillment has containers, including on cartons an operator assigned stores to by hand.

Rollout note: takes effect per integration once the destination grouping is set on the routing strategy, store codes are added to the integration’s location code mapping, and the trading partner’s live template is updated to emit the store distribution.

improvement

ShipStation: Full Ship-Notify Pages, Timeline For Failed Shipments, Traceable Nightly Job

The ShipStation ship-notify webhook was reading only the first page of a shipment batch, capping it at 100 shipments per call — anything past the hundredth was dropped with no error and no retry. The webhook now walks every page. Measured in production over the last thirty days, 89 batches exceeded that limit and at least 21,565 shipments never reached Endless. A nightly reconciliation job had been backfilling those shipments once a day, so the missing ones only became visible when that job stopped running. Two guards land alongside: a shipment already recorded with the same tracking number is skipped on repeat callbacks, and voided labels are excluded so a canceled label does not mark an order shipped. When ShipStation reports a shipment that Endless cannot apply to the order, the dispatch step now writes a timeline entry tagged as a ShipStation shipment failure, with the human-readable reason and the technical detail kept apart. Forty-one orders in production had been sitting with the fulfillment marked shipped and the order still in progress, with nothing on the timeline saying why; the run still continues over the remaining shipments and only the failing one leaves a trace.

The ShipStation nightly reconciliation writes a summary log on every run, including runs that find nothing to do, with counters for shipments fetched, orders touched, fulfillments matched, fulfillments reconciled, lookback window, and duration. Fetch failures are logged before they propagate — before, that path sat outside the error handler and left no trace — and each per-fulfillment failure records its own error message. Between 2026-07-25 and 2026-08-02 the job had stopped running and produced the same trace as a healthy no-op run; matched versus reconciled now separates those cases. This change makes the job observable; retry, backoff, and rate-limit handling are separate work.

improvement

Shopify: Push Local Fulfillment Changes, Reliable Reconciliation, Structural Sync

On a Shopify order, the Fulfillments tab opens with a banner naming who currently manages the fulfillment orders — the source or Endless. When Endless holds the order and you have restructured the fulfillments locally — split one, canceled one, added a new one — an Update fulfillment orders button pushes those changes back to Shopify. The sync runs in the background, the tab re-fetches when it finishes, and the button disappears once both systems match. The button stays disabled while any line has unassigned or over-covered units — a partial set is not something the source can accept — and lists the offending lines so you know what still needs coverage. When a sync fails, order timeline events show an expandable More details row with the Shopify error, the fulfillment order it refers to, and the destination location, instead of a bare failure line.

Fulfillment changes made in Endless — moving items between buildings, splitting a fulfillment, merging fulfillments — did not always take hold on the Shopify side. A structural edit could invalidate the link between the two systems in cases where Shopify could not rebuild its own fulfillment plan, so the change looked applied in Endless while Shopify still held the previous plan. The sync now rebuilds Shopify’s fulfillment orders by moving, merging, and splitting locations until they match Endless, and only rebinds the two together after Shopify confirms. Partial or rejected changes stay visibly unsynchronized on the order rather than looking done, so a divergence is obvious and retrying the sync resolves it. Source-owned changes and integrations that do not sync fulfillment plans behave as before.

The Shopify order reconciliation was reading the same window of recent orders on every run and reprocessing orders it had already handled, which added duplicate fulfillment warnings to the timeline for the same underlying condition. Each successful run now moves its start point to when that run began, so the next pass reads new activity forward from there instead of re-reading everything since the day started. A failed run holds its position, so nothing is skipped. Webhook handling is unchanged.