Changelog
Each entry is the diff between two published schemas, classified as breaking, dangerous or safe. Anything newer than the last cut appears as unreleased.
2026-11-02
Finance: continuity of the lots and the escrow of the former site (docs/adr/0107 amendment). SellerBalanceView gains awaitingMillimes and awaitingSlices — awaited funds: delivered or card-paid orders whose money has not arrived yet, in no balance — and releaseSchedule, the escrow by release day (Tunis day, at most 60 days, one ReleaseDayView per day: day, amountMillimes, slices). SellerStatementView now reads the lot as a statement to be paid: source (platform or legacy), shopName, paidMillimes, residualMillimes, inFlightMillimes (payouts in a bank batch), paymentStatus (unpaid, partial, paid, deferred), deferredReason and deferredAt, payments (the payments recorded or scheduled on the lot), deductions (the Wamia invoices settled by deduction at this close, one SellerInvoicePaymentView per invoice), legacyTransactionIds and odooBillRef for a lot carried over from the former site. SellerFeeInvoiceView gains paidMillimes, paymentStatus and hasXlsx (the line-by-line workbook exists). Additions only.
- type_added ReleaseDayView — OBJECT
- field_added SellerBalanceView.awaitingMillimes — Float!
- field_added SellerBalanceView.awaitingSlices — Int!
- field_added SellerBalanceView.releaseSchedule — [ReleaseDayView!]!
- field_added SellerFeeInvoiceView.hasXlsx — Boolean!
- field_added SellerFeeInvoiceView.paidMillimes — Float!
- field_added SellerFeeInvoiceView.paymentStatus — String!
- type_added SellerInvoicePaymentView — OBJECT
- field_added SellerStatementView.deductions — [SellerInvoicePaymentView!]!
- field_added SellerStatementView.deferredAt — DateTime
- field_added SellerStatementView.deferredReason — String
- field_added SellerStatementView.inFlightMillimes — Float!
- field_added SellerStatementView.legacyTransactionIds — [String!]
- field_added SellerStatementView.odooBillRef — String
- field_added SellerStatementView.paidMillimes — Float!
- field_added SellerStatementView.paymentStatus — String!
- field_added SellerStatementView.payments — [PayoutView!]!
- field_added SellerStatementView.residualMillimes — Float!
- field_added SellerStatementView.shopName — String
- field_added SellerStatementView.source — String!
2026-11-01
Shipments: a shipment may leave in several packages under one tracking number (docs/adr/0212). ApiShipmentView gains packageCount, the number of packages announced to the carrier, and packages, one ApiShipmentPackageView per package (packageIndex from 1, parcelNo, label — the label of that package, AFEX prints <tracking>P01, <tracking>P02… — and weightGrams, the weight read at the bench, null until the package is closed). A single-package shipment has packageCount 1 and one element in packages; accounting and COD stay per shipment. Addition only. Returns: ReturnArrivalView gains packageIndex and packageCount, the package received at the dock and the shipment's total when it had several (null for a single package); the shipment is back only once every package is scanned. Addition only.
- type_added ApiShipmentPackageView — OBJECT
- field_added ApiShipmentView.packageCount — Int!
- field_added ApiShipmentView.packages — [ApiShipmentPackageView!]!
- field_added ReturnArrivalView.packageCount — Int
- field_added ReturnArrivalView.packageIndex — Int
2026-10-30
Catalogue: ProductFlags exposes shipsAsIs, true when the item leaves without a Wamia container (the “Ships as is” field of the Logistics set): the warehouse only applies the label and the document tape, and the slice is billed the “no container” rate only (docs/adr/0209). Addition only. Dock appointments: AppointmentSlotView gains closedReason, why the platform calendar closes the facility over that slot (a public holiday, an inventory — docs/adr/0173); remaining is then 0 and apiBookInboundAppointment, apiRescheduleInboundAppointment, apiBookWithdrawalAppointment and apiRescheduleWithdrawalAppointment refuse the slot with that reason; null when the facility is open. Addition only. Webhooks: the inbound.* and withdrawal.* families gain inbound.slot_closed and withdrawal.slot_closed, sent when the facility closes over an already booked slot (appointmentId, startsAt, reason); nothing is moved for you, rebook with apiRescheduleInboundAppointment or apiRescheduleWithdrawalAppointment. Addition only.
- field_added AppointmentSlotView.closedReason — String
- field_added ProductFlags.shipsAsIs — Boolean
2026-10-29
Drop-off visits and the slot deadline (docs/adr/0207): OrderSliceView gains slotDueAt (by when a dock slot must be booked for a cross-dock slice), sellerClock (SellerClockView: the store's next obligation and its deadline — SellerClockKind: ack, slot, arrival, pickup or none) and dropoffVisit (DropoffVisitView: the drop-off visit the slice follows, with its DropoffRunDecision, its dock appointment, its facility and the shipments riding it, DropoffVisitShipmentView). SliceInboundView gains appointmentId, the dock slot covering the shipment — its own or the visit's. Additions only.
- type_added DropoffRunDecision — ENUM
- type_added DropoffVisitShipmentView — OBJECT
- type_added DropoffVisitView — OBJECT
- field_added OrderSliceView.dropoffVisit — DropoffVisitView
- field_added OrderSliceView.sellerClock — SellerClockView!
- field_added OrderSliceView.slotDueAt — DateTime
- type_added SellerClockKind — ENUM
- type_added SellerClockView — OBJECT
- field_added SliceInboundView.appointmentId — String
2026-10-27
Returns and orders (docs/adr/0200, 0201): RmaItemView gains variantLabel, imagePath, unitPriceMillimes and lineQuantity (the line as it was sold); RmaExchangeSummaryView gains targetSku, targetLabel, replacementSliceNo and replacementSliceStatus (the replacement article and the slice shipping it); RmaView gains customerHistory (RmaCustomerHistoryView: returns requested, completed, rejected, those of the last 365 days and the total refunded to the shopper). OrderSliceView gains kind (OrderSliceKind: SALE, EXCHANGE or WARRANTY_REPLACEMENT) and sourceRmaId, the return a replacement slice comes from. Additions only.
- type_added OrderSliceKind — ENUM
- field_added OrderSliceView.kind — OrderSliceKind!
- field_added OrderSliceView.sourceRmaId — String
- type_added RmaCustomerHistoryView — OBJECT
- field_added RmaExchangeSummaryView.replacementSliceNo — String
- field_added RmaExchangeSummaryView.replacementSliceStatus — String
- field_added RmaExchangeSummaryView.targetLabel — String
- field_added RmaExchangeSummaryView.targetSku — String
- field_added RmaItemView.imagePath — String
- field_added RmaItemView.lineQuantity — Int!
- field_added RmaItemView.unitPriceMillimes — Float!
- field_added RmaItemView.variantLabel — String
- field_added RmaView.customerHistory — RmaCustomerHistoryView
2026-10-26
Returns: RmaView gains returnMethod (EXPRESS_PICKUP, DROPOFF, CARRIER, null until the returns desk decides), pickupCollectedAt (when a Wamia Express driver collected the parcel at the customer's) and pickup, the state of that home pickup (ReturnPickupView: stop, route and its day, driver's display name, status, attempts, last failure reason); null without a planned pickup. The ExpressStopStatus and ExpressRouteStatus enums come with it. Door exchange (docs/adr/0199): RmaReturnMethod gains CARRIER_EXCHANGE — the carrier brings the replacement and takes the article back at the customer's; RmaView exposes returnShipment (RmaReturnShipmentView: kind exchange or return_document, carrier, tracking number and link, status, attempts, acknowledgement, RmaCarrierTicketView carrier tickets), eligibilityOutcome (ExchangeEligibilityOutcome: ALLOW_DOOR_EXCHANGE, EXCHANGE_AFTER_INSPECTION, PICKUP_ONLY, DENY_EXCHANGE) and, for staff, eligibilitySnapshotJson, riskHold (RmaRiskHoldView, the part held on the wallet) and unreturnedReportedAt. RefundLineView says awaitingProof, proofUploadedAt and proofUploadedByUserId for a manual transfer waiting for its proof; ReturnArrivalView.doorExchange tells the dock an exchange is coming back. RmaView also gains returnCarrierCode and returnCarrierRuleId: the carrier taking the return back and the Returns rule that chose it (null until a rule has decided).
- type_added ExchangeEligibilityOutcome — ENUM
- type_added ExpressRouteStatus — ENUM
- type_added ExpressStopStatus — ENUM
- field_added RefundLineView.awaitingProof — Boolean!
- field_added RefundLineView.proofUploadedAt — DateTime
- field_added RefundLineView.proofUploadedByUserId — String
- field_added ReturnArrivalView.doorExchange — Boolean!
- type_added ReturnPickupView — OBJECT
- type_added RmaCarrierTicketView — OBJECT
- type_added RmaReturnMethod — ENUM
- type_added RmaReturnShipmentView — OBJECT
- type_added RmaRiskHoldView — OBJECT
- field_added RmaView.eligibilityOutcome — ExchangeEligibilityOutcome
- field_added RmaView.eligibilitySnapshotJson — String
- field_added RmaView.pickup — ReturnPickupView
- field_added RmaView.pickupCollectedAt — DateTime
- field_added RmaView.returnCarrierCode — String
- field_added RmaView.returnCarrierRuleId — String
- field_added RmaView.returnMethod — RmaReturnMethod
- field_added RmaView.returnShipment — RmaReturnShipmentView
- field_added RmaView.riskHold — RmaRiskHoldView
- field_added RmaView.unreturnedReportedAt — DateTime
2026-10-23
Withdrawals: WithdrawalRequestView gains holdUntil, when the units staged at the bench go back to storage unless a dock slot is taken (stagedHoldHours after they were ready, or after a missed slot); null while a slot is booked or when the site serves from the shelves. Dashboard: SellerDashboardProductView gains imagePath, the product thumbnail (/i/<asset>/thumb.webp), null without a ready image.
- field_added SellerDashboardProductView.imagePath — String
- field_added WithdrawalRequestView.holdUntil — DateTime
2026-10-22
Offers: OfferView and OfferInput gain sellerSku, your own reference for the article in your system (ERP, point of sale, spreadsheet). It is unique per shop, case-insensitively, and Wamia never uses it for operations: sku stays Wamia’s reference, printed on labels and scanned in the warehouse. Omitted, sellerSku is kept; empty, it is cleared; a reference another of your offers already carries is refused. The q search of myOffersPage matches it too (docs/adr/0192).
- field_added OfferInput.sellerSku — String
- field_added OfferView.sellerSku — String
2026-10-16Breaking · 2
Withdrawals: a withdrawal now follows the same route as a reception (docs/adr/0185). WithdrawalStatus gains SCHEDULED, PREPARING, READY, ARRIVED, CLOSED (handed over in full), HANDED_OVER (handed over in part, with a shortfallReason per line) and NO_SHOW; PICKED is removed (breaking: PICKED becomes READY, and a request handed over earlier becomes CLOSED; treat any unknown value as an intermediate state). WithdrawalRequestView exposes reference (RT-YYYY-N), appointment (WithdrawalAppointmentView: dock, start, end, status), readyAt, arrivedAt, closedAt, noShowAt, cancelReason, shopRepresentative, photoKeys, facilityCode, stagingBarcode, atRisk and the line and unit counters (lineCount, requestedUnits, stagedUnits, handedUnits, openTasks, totalTasks). New mutations: apiBookWithdrawalAppointment and apiRescheduleWithdrawalAppointment (no idempotency key, slots from apiInboundSlots); approval now reserves the units. Webhooks: withdrawal.scheduled, withdrawal.no_show and withdrawal.cancelled are added; withdrawal.requested, decided, ready and handed_over keep their names. Receptions: InboundShipmentView gains orderNo, sliceNo, photoKeys and shopRepresentative, InboundLineView needsLabels and needsMeasure, InboundShipmentDetailView reports (InboundReportView, the versioned reception report, docs/adr/0183). Returns: RmaView gains logistics (ReturnLogisticsView: the arrival at the returns dock, its status, the stocked / cross_dock / mixed mode, and on request ReturnArrivalView with its lines, piece-by-piece outcomes — ReturnDestination: stock, withdrawal, damaged, quarantine, missing — and the shop withdrawal opened for cross-dock units, docs/adr/0186); WithdrawalRequestView gains openReturnTasks and totalReturnTasks. Pickups: PickupTaskView gains qrScannedAt and InboundShipmentDetailView pickupQr (PickupQrView). Payouts: PayoutView.organizationId becomes optional (breaking) because a payout may go to a delivery partner; payeeKind (organization | partner), partnerId, partnerName and partnerStatementId are added.
- field_type_changed PayoutView.organizationId — String! → String
- enum_value_removed WithdrawalStatus.PICKED
- enum_value_added WithdrawalStatus.ARRIVED
- enum_value_added WithdrawalStatus.CLOSED
- enum_value_added WithdrawalStatus.NO_SHOW
- enum_value_added WithdrawalStatus.PREPARING
- enum_value_added WithdrawalStatus.READY
- enum_value_added WithdrawalStatus.SCHEDULED
- field_added InboundLineView.needsLabels — Boolean!
- field_added InboundLineView.needsMeasure — Boolean!
- type_added InboundReportView — OBJECT
- field_added InboundShipmentDetailView.pickupQr — PickupQrView
- field_added InboundShipmentDetailView.reports — [InboundReportView!]!
- field_added InboundShipmentView.orderNo — String
- field_added InboundShipmentView.photoKeys — [String!]!
- field_added InboundShipmentView.shopRepresentative — String
- field_added InboundShipmentView.sliceNo — String
- operation_added Mutation.apiBookWithdrawalAppointment — WithdrawalRequestView!
- operation_added Mutation.apiRescheduleWithdrawalAppointment — WithdrawalRequestView!
- field_added PayoutView.partnerId — String
- field_added PayoutView.partnerName — String
- field_added PayoutView.partnerStatementId — String
- field_added PayoutView.payeeKind — String!
- type_added PickupQrView — OBJECT
- field_added PickupTaskView.qrScannedAt — DateTime
- type_added ReturnArrivalKind — ENUM
- type_added ReturnArrivalLineView — OBJECT
- type_added ReturnArrivalOutcomeView — OBJECT
- type_added ReturnArrivalStatus — ENUM
- type_added ReturnArrivalTransferView — OBJECT
- type_added ReturnArrivalView — OBJECT
- type_added ReturnArrivalWithdrawalView — OBJECT
- type_added ReturnCountMethod — ENUM
- type_added ReturnDestination — ENUM
- type_added ReturnLocationView — OBJECT
- type_added ReturnLogisticsView — OBJECT
- field_added RmaView.logistics — ReturnLogisticsView
- type_added WithdrawalAppointmentView — OBJECT
- field_added WithdrawalRequestView.appointment — WithdrawalAppointmentView
- field_added WithdrawalRequestView.arrivedAt — DateTime
- field_added WithdrawalRequestView.atRisk — Boolean!
- field_added WithdrawalRequestView.cancelReason — String
- field_added WithdrawalRequestView.closedAt — DateTime
- field_added WithdrawalRequestView.facilityCode — String!
- field_added WithdrawalRequestView.handedUnits — Int!
- field_added WithdrawalRequestView.lineCount — Int!
- field_added WithdrawalRequestView.noShowAt — DateTime
- field_added WithdrawalRequestView.openReturnTasks — Int!
- field_added WithdrawalRequestView.openTasks — Int!
- field_added WithdrawalRequestView.photoKeys — [String!]!
- field_added WithdrawalRequestView.readyAt — DateTime
- field_added WithdrawalRequestView.reference — String!
- field_added WithdrawalRequestView.requestedUnits — Int!
- field_added WithdrawalRequestView.shopRepresentative — String
- field_added WithdrawalRequestView.stagedUnits — Int!
- field_added WithdrawalRequestView.stagingBarcode — String
- field_added WithdrawalRequestView.totalReturnTasks — Int!
- field_added WithdrawalRequestView.totalTasks — Int!
2026-10-11
Orders: each slice (OrderSliceView) exposes liveSale, true when at least one item was added from the shop’s live stream and rated at the schedule’s live commission (0% by default); false otherwise. Commission amounts stay reserved to Wamia staff (docs/adr/0113). Offers: OfferView gains organizationName (the localized name of the shop selling the offer) and variantLabel (the variant in plain words, for example “256 GB · Blue”); both optional fields name an offer outside its shop's context, for example when several shops sell the same product page (buy box, docs/adr/0029). Corrections: OrderSliceView and InboundLineView expose correctionId, the reference (COR-YYYY-N) of the last manual correction that touched the slice or the receiving line; null until one happens. A correction takes back an action recorded by mistake (a receipt, a step marked by hand) and leaves a trace in the corrections ledger (docs/adr/0171). Settlement: OrderSliceView exposes wamiaFundedMillimes, what Wamia gave away on the slice (Wamia voucher share, season deals) out of its own margin; the amount reduces neither the seller’s gross, nor the net, nor the commission base (docs/adr/0172). Staff only. Languages: LocalizedText and LocalizedTextInput gain tn, Tunisian Derja written in Arabic script, next to fr, en and ar; the field is optional and a missing value falls back to ar then fr. Text sent through Connect is recorded as imported and is never overwritten by Wamia’s machine translation (docs/adr/0175).
- field_added InboundLineView.correctionId — String
- field_added LocalizedText.tn — String
- field_added LocalizedTextInput.tn — String
- field_added OfferView.organizationName — LocalizedText
- field_added OfferView.variantLabel — String
- field_added OrderSliceView.correctionId — String
- field_added OrderSliceView.liveSale — Boolean!
- field_added OrderSliceView.wamiaFundedMillimes — Float!
2026-10-10
Advertising: AdChannel gains META_POOL (the shared Meta catalogue, the default channel of a boost) and META_SOLO (a dedicated single-product Meta ad); META remains the channel of the legacy dedicated ad sets. A client reading AdBoostView.channel must accept these values (docs/adr/0098). Logistics: offers stocked at Wamia are topped up by appointment and taken back with a withdrawal. apiInboundShipments takes origin (SELLER_DECLARED for top-ups, ORDER_DRIVEN for cross-dock transfers); apiInboundSlotGrid returns dock slots per day over at most 14 days and apiRescheduleInboundAppointment moves a booked appointment (inbound.rescheduled event). apiStockedPositions exposes the warehouse count (onHandQty, reservedQty, availableQty), cursor-paginated; StockOfferFactsView carries fulfilmentMode. Batch results (ApiBatchItemResultView) gain skipped and skipReason: apiDeclareStocks now skips stocked offers with skipReason stocked_offer instead of overwriting the warehouse count. New webhook families inbound.* and withdrawal.* (docs/adr/0162).
- enum_value_added AdChannel.META_POOL
- enum_value_added AdChannel.META_SOLO
- field_added ApiBatchItemResultView.skipReason — String
- field_added ApiBatchItemResultView.skipped — Boolean
- type_added ApiStockedPositionPage — OBJECT
- type_added ApiStockedPositionView — OBJECT
- type_added AppointmentSlotDayView — OBJECT
- operation_added Mutation.apiRescheduleInboundAppointment — InboundShipmentView!
- arg_added Query.apiInboundShipments(origin) — InboundOrigin
- operation_added Query.apiInboundSlotGrid — [AppointmentSlotDayView!]!
- operation_added Query.apiStockedPositions — ApiStockedPositionPage!
- field_added StockOfferFactsView.fulfilmentMode — FulfilmentMode
2026-10-09
Orders: each slice (OrderSliceView) splits its gross handling fee into packagingBoxMillimes (the container) and packagingProtectionMillimes (bubble wrap, tape, void fill), TTC; their sum is the gross as before. Catalogue: ProductFlags exposes retailBoxed, true when the item ships in its retail box (the “Ships in its retail box” field of the Logistics set); a bare item gets one more lap of bubble wrap (docs/adr/0158).
- field_added OrderSliceView.packagingBoxMillimes — Float!
- field_added OrderSliceView.packagingProtectionMillimes — Float!
- field_added ProductFlags.retailBoxed — Boolean
2026-10-08
Orders: each line (OrderLineView) exposes promoDiscountMillimes, the shop-funded discount on the line (promo price, flash, sale or quantity deal); 0 without a promotion. The line keeps its catalogue price; the discount is deducted from the payout like fees (docs/adr/0150).
- field_added OrderLineView.promoDiscountMillimes — Float!
2026-10-07
Shop statement: each ledger line exposes entryId, the id of the journal entry it belongs to (the drill-down key for daily storage fees). Media: MediaAsset exposes kind (image or video), videoUrl, posterUrl and durationMs for the clips embedded in product descriptions; descriptions are now rich HTML (formatting, lists, tables, pictures and videos). Logistics: ProductVariant exposes fragile, liquid and sharp (handling) plus the dimensions the warehouse measured at receiving (measuredWeightGrams, measuredLengthMm, measuredWidthMm, measuredHeightMm, measuredAt — read-only); ProductFlags gains battery (BatteryContent) and thisSideUp; Product exposes prepSteps, the extra protections requested at packing.
- type_added BatteryContent — ENUM
- field_added MediaAsset.durationMs — Int
- field_added MediaAsset.kind — MediaAssetKind!
- field_added MediaAsset.posterUrl — String
- field_added MediaAsset.videoUrl — String
- type_added MediaAssetKind — ENUM
- field_added Product.prepSteps — [String!]!
- field_added ProductFlags.battery — BatteryContent
- field_added ProductFlags.thisSideUp — Boolean
- field_added ProductVariant.fragile — Boolean!
- field_added ProductVariant.liquid — Boolean!
- field_added ProductVariant.measuredAt — DateTime
- field_added ProductVariant.measuredHeightMm — Int
- field_added ProductVariant.measuredLengthMm — Int
- field_added ProductVariant.measuredWeightGrams — Int
- field_added ProductVariant.measuredWidthMm — Int
- field_added ProductVariant.sharp — Boolean!
- field_added SellerLedgerLineView.entryId — String!
2026-10-06
Shop obligations by fulfilment mode: slices stocked at Wamia are read-only (apiAcknowledgeSlice and apiMarkSlicePrepared answer VALIDATION_FAILED); cross-dock slices expose the acknowledgement deadline, the shop's acknowledgement or decline and the linked inbound shipment (reference, status, due date, slot).
- field_added OrderSliceView.inbound — SliceInboundView
- field_added OrderSliceView.sellerAckDueAt — DateTime
- field_added OrderSliceView.sellerAcknowledgedAt — DateTime
- field_added OrderSliceView.sellerDeclineReason — String
- field_added OrderSliceView.sellerDeclinedAt — DateTime
- type_added SliceInboundView — OBJECT
2026-10-05
First public version of Wamia Connect: Connect flow (PKCE) and pairing, bulk offers and stock, media by URL, orders and returns, signed webhooks, guardrails and the sandbox.
No schema change.
Versioning policy
The schema only grows. Fields are deprecated at least 6 months before removal, and connectors get a minimum-version bump instead of a silent break. Breaking changes are announced here and by e-mail to key owners.