Skip to main content

What’s new at Endless

Changelog

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

improvement

QuickBooks: Map Suppliers To Vendors, And A Safer Push

The QuickBooks Data Mapping tab has a Suppliers table. Each supplier gets a picker that searches your QuickBooks vendors as you type, and selections stage in the table so you can work through several and save them together. Pull vendors re-imports the list without leaving the tab, and a vendor already mapped to one supplier is unavailable in the others, so the same vendor cannot be used twice. If you connected QuickBooks before this, run Import Vendors once so vendors you have already synced appear in the picker.

Two changes on the product header. Push to Accounting asks for confirmation before it runs, rather than overwriting the QuickBooks record on the first click. The Synced to accounting badge is gone: it recorded that a push had happened, not that the two records still agreed, so a product that had drifted still read as up to date.

Sales enabled now defaults on when you apply defaults, matching QuickBooks’ requirement that inventory and service items carry an income account; records created with it off were refused. A company with more than one accounting integration connected can push to the one it names rather than whichever was found first.

improvement

Small Interface Polish

Six small fixes across the app.

Product sheet: smoother tab switching and scrolling. Switching between the Key Info, Images, and Relationships preset tabs on the product sheet, and scrolling down a catalog with large product photos, used to stutter — every cell was being rebuilt on each tab change and every image in the row was being decoded whether it was on screen or not. Tab switches, quickview open and close, and vertical scrolling now stay smooth: cells reconcile in place instead of remounting, images decode only when they come into view, and the Images column caps at four thumbnails with a +N overflow label so a row with dozens of photos no longer pulls all of them at full resolution.

Order detail tables sort. Two tables on the order detail view sort now. Order items sort by item, price, discount, quantity, or total; fulfillment items sort by product or quantity. Blank values move to the bottom, equal values keep their original order, and sorting is disabled while you are in bulk edit or single item edit, since those modes need to hold the original row order.

Sidebar collapse preference sticks. The sidebar’s collapsed or expanded state sticks across page loads. Toggling by click or with the ⌘\ shortcut saves the choice right away, and returning from a narrow viewport — where the sidebar auto-collapses — restores the last preference you set rather than an older one. The ⌘\ shortcut is disabled inside Settings, where the sidebar always stays expanded.

Date picker: sized right and stays on screen. The date picker’s day-number grid is the same size as the weekday row and the month/year caption above it. Day numbers had been sitting a step larger than everything around them since the shared calendar was inheriting the browser’s default text size, so the fix touches every date field in the app — Purchase Order Issue Date, Shipment Received Date, and every other picker built on the shared calendar. The popover also no longer sits flush against the edge of the browser window. Opening a date field close to the right edge — the Received Date on the Shipment quickview was the reported case — had been clipping the popover off screen; it now keeps eight pixels of padding from the edge on both sides, so even the wide three-month range picker stays fully visible down to iPad mini widths.

Sales channel picker searches and no longer stops at twenty. The sales channel dropdown used across the app only ever loaded the first twenty channels and had no search, so companies with more than that could not pick their older channels from anywhere — and integration data mappings pointing at those channels rendered a raw ID instead of the channel name. The picker is now a searchable list. It shows the twenty most recent channels by default, searches by name against the server, and always resolves the currently selected channel by ID so the name shows up even when the channel sits outside the loaded page or has been archived. Integration Data Mapping tabs read the channel name straight off the mapping, so archived channels and channels past the old cap render with their real names in place of the ID they used to show.

Product confirmation modals: body copy is the right size. The body copy in the Clone Product, Archive Product, and Unarchive Product modals was rendering larger than the modal title above it. All three share one modal underneath, so the fix lands on all three at once. The description now uses the smaller size that matches the rest of the modal.

fix

Archiving Large Product Attributes No Longer Stalls

Archiving a product attribute definition used to update every value on every product one at a time. Definitions with roughly 153,000 values could stall out and roll the archive back, so a large attribute could not actually be archived. Archiving is now a single change on the definition itself and hides its values across every product through that change, so a large definition archives as quickly as a small one.

Clearing a value on a product now removes it rather than leaving an archived-empty record in place. Restoring a definition brings back only the values that still exist, and filters, integrations, unit-of-measure conversion, cloning, and value suggestions all follow the parent’s visibility.

feature

Product Costs: Defaults, Estimates, And Bulk Tools

The three product-level costs — Unit Cost, Landed Cost, and Dropship Unit Cost — read as Default Unit Cost, Default Landed Cost, and Default Dropship Unit Cost on the product sheet, the product detail, purchase orders, bulk edit, and the CSV import and export columns. The new name reflects how the value is used: a default that a supplier estimate can override, entered by a person, and blank if none has been set. Gross margin uses Default Landed Cost when it’s present and falls back to Default Unit Cost, so a product with only a unit cost still shows a margin figure.

The Pricing & Costs section on a product separates defaults from estimates. Default Unit Cost, Default Landed Cost, and Default Dropship Unit Cost sit in editable cards at the top. Below them, a Cost Estimates table lists every estimate — your own or from a supplier — with add, edit, duplicate, and archive on each row, a popover for the labor, materials, packaging, freight, and duties breakdown, and a way to promote a single value from an estimate straight to the matching default. Each estimate can carry an effective date, and Current, Scheduled, and Archived badges show what’s live, what’s queued to take over, and what’s been retired. An estimate no longer needs a supplier attached — the question “what should this cost to make?” is stored directly. Profitability at the top of the page is computed from MSRP and Default Landed Cost, falling back to Default Unit Cost if the landed value isn’t set. Completeness for a product accepts either the full stocked cost set or just the dropship unit cost, so a dropship-only product no longer needs a stocked cost to count as complete.

Product Cost Estimates now round-trip through CSV, supplier costs and internal estimates together. Imports create or update by SKU, supplier, cost type, and quantity tier, and carry lead times and cost breakdowns row for row. Row-level errors call out what did not import. Omitting a cost field leaves the current value alone; blanking it clears it. Unit cost is required and must be greater than zero, and effective date is a supported column. Exports respect the current filters on the Products page and produce a file that can be edited and re-imported directly. The Products list Import and Export actions have also been consolidated behind two menus, each opening a dialog that lets you pick Products, Product Cost Estimates, or Relationships. Command palette, table menu, and first-run empty state all point at the new dialog.

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.

feature

Dropship On Fulfillment Orders: Supplier Costs And Email Delivery

Fulfillment orders now carry the dropship workflow end to end. When a fulfillment has a supplier, you can capture and edit unit costs, line totals, and shipping and other charges on the fulfillment itself. Assigning or updating a supplier can optionally refresh line costs from the supplier’s dropship cost tiers with a fallback to the product default; keeping the option off leaves costs untouched, and any line with no matching cost is cleared rather than left stale. Costs travel through to the fulfillment PDF and the public share view, including a supplier cost summary. The public share header no longer shows the sales order number.

A new Email Fulfillment Order action sends the share view directly from Endless. To and CC recipients are separate, each address gets its own revocable link, and the dialog suggests every supplier contact with an email, the building’s email address, and the current user, so the right recipients are one click away. Buildings now hold one primary email address, editable from a Contact Information card on the building’s General tab and reachable from the fulfillment email dialog. Delivery goes through SendGrid and retries asynchronously if it fails.

feature

GS1 Prefixes, UPC Assignment, And Packaging GTINs

Companies with a GS1 licence can now manage their prefixes in Endless and assign UPCs from them to products, without hand-typing codes or tracking a spreadsheet on the side. Each prefix records its item-reference space, so the number of codes still available comes straight from what the licence actually grants, and Endless will not mint the same code twice or hand out a code that falls inside another company’s prefix. Blocks of assigned codes can be exported to CSV.

UPC assignment lives on the product. Clearing a UPC keeps other product fields untouched, and the app asks whether to release the code back to the prefix once the product has moved off it — kept as a separate step because GS1 does not allow a released code to be reused. Product packaging can also carry GTINs, tied to the same prefix rules. The feature is in early access and available on request.

improvement

Suppliers: Archived Status, Legal Name, And Cost-Driven Relationships

Three updates to Suppliers.

Archived suppliers show as Archived. An archived supplier used to still show Active or Inactive on the list and detail page, because archiving only marked the record archived and left the underlying status alone. The badge now shows Archived when the supplier is archived, so the status column matches the detail page. Archiving from the detail page or quick view also keeps the page open, so the archived banner and the Archived badge update in place instead of the view closing.

Suppliers carry a Legal Name alongside their display name, so the name that appears on paperwork and accounting records does not have to be the same one shown in the app. Legal Name is available in the Add Supplier dialog, editable from the Company Details card on the supplier’s detail page, and shown as a sortable column on the Suppliers list. Optional throughout — empty renders as an em-dash — and searchable from the Suppliers list search box. The existing Supplier Name column and the Edit Name action have been renamed to Supplier Display Name and Edit Display Name, so it is clear which name a screen is reading.

Supplier–product relationships now come from product costs. Adding a product cost for a supplier creates the relationship on its own, and archived relationships are restored on the same signal. Purchase orders no longer create these relationships as a side effect, so a purchase order for a supplier that has never quoted a cost for a product does not link the two. Imports keep the supplier’s minimum order quantity intact: the supplier link is created before its costs, so the imported MOQ is not overwritten by the default. Purchase order line lookups read cost and MOQ from the supplier relationship directly.

fix

Integrations Without A Warehouse Lookup Can Be Mapped To A Building Again

Six integrations — Veracore, Infoplus, Jazz, MasonHub, QBO, and ShipHero — showed a warehouse mappings table on their Data tab with no way to add a mapping, so a building could not be pointed at any of them as an inventory source. Manage Mappings only appears for integrations that can fetch their own warehouse list, and Add Mapping was hidden unless an integration opted in.

Any integration without a fetchable warehouse list now shows Add Mapping by default, and the empty state tells you which option to use — Manage Mappings when the integration can look up its own warehouses, Add Mapping with the external code the system sends when it cannot.