Release 2026.09-R4
Released September 9, 2026.
New Shipment page
A redesigned Shipment page is available to every Dashboard user. The current page stays the default. A banner on it offers the new design: select See what's new, then Try the new page. Your choice is saved for you on each tenant.
The new page opens with a header showing the shipment's references, merchant, delivery type and delivery option. It also shows the shipment's alerts and its progress through the shipment lifecycle. Details are grouped into tabs: Contents, Money, Customs, Documents, Carrier & Route, Attributes and Activity. A consolidated parent shipment shows Children in place of Customs. The Activity tab lists what happened to the shipment. Filter it by All, User, System, API or Webhook, and sort newest or oldest first.
To go back, select Switch to legacy page and pick the reason you're switching back.
Schedule Collection and carrier pickup requests
Scheduling a collection now also requests a pickup from the carrier, and the shipment shows where that request stands.
- In the Dashboard: Reschedule Collection and Reschedule Delivery are now Schedule Collection and Schedule Delivery. The new names apply on the shipment page, in the shipment list and in bulk actions. Schedule Collection saves the collection window and requests a pickup from carriers that take pickup requests, unless one is already requested or booked. A new Pickup Request field on the shipment page shows Not requested, Requesting pickup, Pickup booked or Pickup failed. Hover over it for the pickup ID or the carrier's reason for a failure.
- Auto Schedule Pickup in carrier account settings no longer depends on Auto Ready To Ship. It requests a pickup as soon as a shipment is booked, and shows for every carrier that supports pickups.
- Shipment list filters: the Carrier Pickup Status filter is now Carrier Pickup Request, with Pickup Failed, Requesting Pickup and Pickup Booked. The Scheduling Warning option is now Ready-to-ship Warning.
- Via the API:
POST /shipments/{shipment_id}/schedule-collectionsets the collection window withscheduled_dateandscheduled_time_slot_id, orscheduled_fromandscheduled_to. With no body, it uses the pickup hours on the carrier account. The first call also requests the carrier pickup. It never changes the shipment status.update-collection-schedulestill works but is deprecated, and its responses carry aDeprecationheader.schedule-deliveryis a new name forupdate-delivery-schedule, and both work. - Ready to ship with a pickup: the shipment moves to Ready to Ship once the carrier confirms the pickup. If the carrier refuses it, the shipment stays Booked and the pickup shows as failed. A pickup the carrier never answers is also marked failed.
- Error triggers: a failed ready-to-ship is now reported with
triggerREADY_TO_SHIPinerror_detailsand in webhooks. Before, it wasSCHEDULING, which now covers failed pickup requests only.
Tracking page updates
The new tracking page, introduced in 2026.07-R1, has these changes:
- Manage my order: customers edit the address, contact number, delivery time and notes in one form. One save sends one request and one confirmation email. Before, each field was saved on its own. Delivery time windows that have already passed are no longer offered for today.
- Live delivery map: the map draws a straight line from the driver to the delivery address. It shows the carrier's estimated arrival time when the carrier sends one. It shows only for forward shipments out for delivery. If the map can't load, the page leaves it out. The same map change applies to the older tracking pages.
- Orders with several shipments: the summary and progress bar count forward shipments only, and show cancelled shipments separately. An order counts as delivered once every forward shipment that isn't cancelled is delivered. The feedback and Raise a claim sections now show for these orders too. Feedback is saved against those shipments only.
- Status text: the timeline reads Order Placed, Processing, Shipped, Out for Delivery, Delivered. A shipment in error reads "We're sorting out an issue with this shipment and will keep you updated." Shipments not yet shipped no longer read "awaiting stock". With no customer name, the greeting reads "Order #…".
- Placeholders on the live page: sections without the content they need no longer show on the live page. This covers a promo banner with no image, Shop links with no URL, empty product recommendations and the feedback note before delivery. The page editor still shows them in the preview, with a warning where setup is missing.
- Layout and language: on wide screens the content stays centered at a fixed width. The driver card and item counts now follow the page language.
- View invoice: the link in the order details is hidden for now.
In the Dashboard, the order actions menu has a new View Customer Tracking Page option. It opens the customer's tracking page for the order.
New carrier: Parcel
Parcel delivers across Bahrain, with instant, same-day and next-day delivery. Set up the account with your API key and Parcel branch, then choose the Vehicle (car, bike, van or chiller) and Order Type. For next-day delivery, you also set the pickup slot, the delivery slot, and whether to deliver the same day.
Webhook registration checks
Carriyo now refuses webhook configurations that could never fire.
- Via the API:
POST /webhooksand webhook updates return400when the configuration has no trigger for its entity type. Shipment webhooks neednotify_statusor at least onenotify_*trigger. Return request webhooks neednotify_status,notify_rma_received_itemsornotify_rma_returned_items. Inventory webhooks neednotify_statusset to["ALL_INVENTORY_UPDATES"]. Other entity types neednotify_status. - Inventory webhooks are saved with
merchantsset to["_ANY"], whatever you send, because inventory events aren't tied to a merchant. For other entity typesmerchantsis still required. headersis optional. It is saved as an empty object when you leave it out.- In the Dashboard: under Settings > Webhooks, you can't save a webhook until it has at least one trigger. A new inventory webhook starts with the inventory trigger selected.
Inventory bulk import
- Via the API:
POST /inventory-events/bulk/importaccepts up to 500 rows per request. A larger request returns400with "bulk import cannot exceed 500 rows". A newskip_unchangedquery parameter leaves rows that don't change the stock out of the event history. They still count towards completing the request. - Duplicate snapshots in one request: several snapshot rows of the same type can name the same inventory key and location. Carriyo applies the one with the newest
event_timestampand rejects the others. Snapshot rows of different types for the same inventory key and location are all rejected. Movement rows always apply. - Dashboard imports and inventory feeds: rows that don't change the stock are no longer added to the event history. Import Inventory Snapshot flags rows that repeat an inventory key and location as Duplicate inventory key and location.
partner_location_id in the fulfillment APIs
Picks, packs, collections and bin locations now use partner_location_id in place of location_id, in requests and responses. The same rename applies to the allocation_history entries on each fulfillment order in order responses and webhooks. Existing records were updated.
Scoped user IDs in audit fields
When someone makes a change in the Dashboard, Carriyo now records the person as their sign-in scope and user ID. Examples are global~jane@example.com for a normal sign-in, and Carriyo-SSO::<tenant>~jane@example.com for SSO. This applies to fields such as held_by and released_by on orders on hold, and created_by_user on manifests. Records saved before this release keep the plain user ID. The Dashboard shows the person's name for both, and the Assigned To filter on return requests finds both.
The user now comes from the verified sign-in token, not from a request header. API clients, connectors and carriers are recorded as before.
Fixes
- Malformed request bodies: a field with the wrong type, or malformed JSON, made order, return, manifest, inventory and Storefront API endpoints return
500with a Base64-encoded body. They now return400with a JSONerrorsarray, for example "Field 'products[0].quantity' has an invalid value or type". - API Access: the API Access page under Settings showed no API key for some users. This hit users with access to all tenants who also had a fulfillment-only role on the tenant. It shows the key again.
- Order custom attributes: the order export now has columns for free-text, number and boolean custom attributes, at order and line-item level. Before, only dropdown attributes got a column. Order import no longer splits free-text custom attribute values at commas.
- Geography conditions in rules: shipping rules and other rules with country, state, city or area conditions now match names regardless of case and extra spaces. Before, a shipment with a padded or differently cased area name could skip a matching rule. A non-breaking space in an address is now kept as a space instead of being removed.
- Shipment list in Safari: the Shipment column is left-aligned again.