Shopify introduce în API-ul GraphQL Admin versiunea 2026-10 o acțiune CANCELED pentru recepția livrărilor de stoc. Unitățile care nu vor ajunge niciodată pot fi marcate explicit, iar aplicațiile pot citi cantitățile anulate pe livrare și pe fiecare linie. Este o schimbare aditivă, fără acțiune obligatorie, iar aplicațiile de pe versiuni anterioare nu sunt afectate (sursa: Shopify Changelog).

Ce se schimbă concret în API

Până acum, API-ul de livrări de stoc avea doar două rezultate posibile pentru o unitate: acceptată sau respinsă. Când un transfer de stoc conținea unități care pur și simplu nu mai ajungeau, aplicațiile nu aveau cum să înregistreze realitatea. Practic, unitățile rămâneau nerecepționate la nesfârșit sau erau înregistrate greșit ca respinse. Diferența nu e cosmetică: o unitate respinsă și una anulată sunt două lucruri complet diferite din perspectiva vânzătorului, a depozitului și a comenzii de achiziție.

Versiunea 2026-10 adaugă CANCELED ca a treia acțiune de recepție, alături de accepted și rejected. Concret, apar două câmpuri noi: totalCanceledQuantity la nivelul obiectului InventoryShipment, care însumează cantitățile anulate pe toate liniile, alături de totalAcceptedQuantity și totalRejectedQuantity; și canceledQuantity la nivel de InventoryShipmentLineItem, alături de acceptedQuantity și rejectedQuantity.

Un detaliu important de urmărit: unitățile anulate contează în InventoryShipment.totalReceivedQuantity. Asta înseamnă că, pe 2026-10, totalul recepționat se descompune complet în acceptat, respins și anulat. Este o schimbare de logică pentru orice interfață sau raport care afișa cele trei valori una lângă alta. Dacă până acum sumele puteau părea că nu se adună, acum au o explicație.

Cum marchezi unitățile care nu vor ajunge

Mecanismul este simplu și se bazează pe o valoare nouă de enum: CANCELED pe InventoryShipmentReceiveLineItemReason. O transmiți ca motiv pe o linie în mutația inventoryShipmentReceive, iar unitățile sunt marcate ca anulate. Alternativ, o poți trimite ca bulkReceiveAction pentru a marca toate unitățile rămase pe livrare drept anulate.

Din exemplul oficial, o mutație care marchează 5 unități dintr-o linie ca anulate și citește înapoi cantitățile actualizate arată așa, pe scurt: apelezi inventoryShipmentReceive cu ID-ul livrării, ID-ul liniei, cantitatea și reason: CANCELED, cu un @idempotent(key: ...), și returnezi totalCanceledQuantity plus canceledQuantity pe nodurile liniilor. Cheia de idempotență este obligatorie pe această mutație începând cu versiunea 2026-04, deci nu e opțională dacă vrei să eviți dublări la retry-uri.

Aici e locul unde se vede dacă echipa ta chiar citește documentația sau doar o parcurge. O cheie de idempotență generată corect, unică pentru fiecare recepție, este diferența dintre un sistem care rezistă la erori de rețea și unul care inventează stoc din greșeală.

Webhook-urile: partea pe care mulți o ratează

Cea mai fragilă zonă nu este API-ul în sine, ci handlerul de webhook. Abonamentele la topicul inventory_shipments/receive_items pe versiunea 2026-10 sau mai nou primesc acum old_canceled_quantity și new_canceled_quantity pe fiecare intrare din items_received. În plus, recepțiile care schimbă doar cantități anulate declanșează acum o livrare.

Pe versiunile anterioare, nimic nu se schimbă: câmpurile anulate sunt omise din payload, iar recepțiile exclusiv de anulare nu declanșează nicio livrare. Este exact tipul de detaliu care produce bug-uri tăcute. Dacă handlerul tău presupune că items_received are mereu aceeași formă sau că o livrare înseamnă obligatoriu o schimbare de cantitate acceptată, s-ar putea să ignori silent evenimente sau să arunci erori pe câmpuri lipsă.

Asta leagă subiectul de un pattern mai larg pe care l-am tot văzut în ultimele luni: integrările care presupun o formă fixă a datelor se sparg la prima schimbare aditivă. Am scris despre asta și în analiza despre paritatea de conținut și workflow-urile validate pentru AI Search, unde concluzia era similară: validarea și testarea se mută dinspre „arată bine” spre „rezistă la variație”.

O altă analogie utilă este cazul Shopify care elimină automaticDiscounts în API 2027-01. Acolo avem o schimbare care rupe, aici una care adaugă. Ambele arată același lucru: ciclul de viață al versiunilor API se scurtează, iar echipele care stau pe versiuni vechi ajung să plătească mai târziu, cu dobândă.

Ce verifici înainte să sari

Nu trata anunțul ca pe un feature de bifat. Întrebările care contează sunt operaționale. Mai întâi: ce citește aplicația ta azi din livrările de stoc și cum afișează progresul recepției? Dacă ai un dashboard sau un sync cu un WMS sau 3PL, trebuie să decizi dacă adaugi a treia categorie sau o lași ascunsă. Ascunderea ei nu e greșită prin definiție, dar trebuie să fie o alegere conștientă, nu o omisiune.

Apoi: cum reacționează handlerul tău de webhook la o livrare care schimbă doar cantitatea anulată? Dacă nu ai testat scenariul, nu ai cum să știi. Și pentru că tocmai am spus că o verificare incompletă nu dovedește absența unei probleme, notează clar: nu avem date care să arate că această schimbare produce erori în conturi reale. Avem doar o schimbare documentată de API și un set de întrebări pe care orice integrare serioasă ar trebui să le pună.

Merită să separi explicit trei lucruri. Constatare măsurată: versiunea 2026-10 adaugă câmpurile și enum-ul descrise mai sus. Ipoteză: handler-ele care nu tratează câmpurile noi ar putea rata evenimente sau produce erori. Recomandare: testează pe un development store înainte de upgrade, exact cum sugerează și documentația. Nu confunda lipsa unui test cu absența unei funcții.

Ce înseamnă pentru tine

Dacă ești antreprenor sau marketer cu un magazin pe Shopify, ce faci cu asta? Concret, depinde cât de mult din operațiunea ta atinge stocul.

Dacă ai un business mic, cu un singur depozit și recepții simple, probabil nu faci nimic acum. Schimbarea este aditivă, iar versiunile vechi rămân neatinse. Dar pune-ți întrebarea corectă pentru 2026: aplicațiile din stack-ul tău, de la ERP la soluția de fulfillment, când trec pe 2026-10? Fiecare versiune sărită peste noapte devine o migrare forțată mai târziu.

Dacă ai un business cu volum real, cu transferuri între depozite, cu un 3PL sau cu comenzi de achiziție sincronizate, subiectul e mai serios. Cifrele de stoc care nu se închid sunt una dintre cele mai scumpe probleme tăcute din ecommerce. Nu prin costul direct, ci prin deciziile de reaprovizionare luate pe date greșite. Dacă până acum unitățile care nu ajungeau erau îngropate ca „respinse” sau lăsate nerecepționate, raportul tău de stoc era deja ușor mincinos. Acum ai un mod corect să închizi acele unități.

La nivel de echipă de marketing, implicația e indirectă dar reală. Disponibilitatea stocului alimentează feed-ul de produse, iar feed-ul alimentează campaniile. Orice sistem care ține stocul mai curat te ajută să nu rulezi reclame pe produse care nu există. Legătura cu măsurarea o regăsești și în analiza despre Google Ads multi-source conversions beta: cu cât datele de bază sunt mai curate, cu atât optimizarea are sens.

FAQ

Trebuie să fac ceva obligatoriu? Nu. Documentația spune explicit că nu este necesară nicio acțiune, iar aplicațiile de pe versiuni anterioare nu sunt afectate. Câmpurile noi și enum-ul nu sunt disponibile pe versiunile pre-2026-10, payload-urile de webhook își păstrează forma actuală, iar recepțiile exclusiv de anulare rămân suprimate.

Ce fac dacă vreau să folosesc acțiunea CANCELED? Treci aplicația pe versiunea 2026-10, interogează totalCanceledQuantity pe livrare și canceledQuantity pe linie acolo unde afișezi sau sincronizezi progresul recepției, transmite reason: CANCELED în inventoryShipmentReceive pentru unitățile care nu vor ajunge, testează pe un development store și confirmă că handlerul de webhook procesează old_canceled_quantity și new_canceled_quantity.

De ce contează că unitățile anulate intră în totalReceivedQuantity? Pentru că pe 2026-10 totalul recepționat se descompune complet în acceptat, respins și anulat. Orice interfață sau raport care afișează aceste valori trebuie să reflecte noile proporții, altfel cifrele par să nu se adune.

Concluzia ALLSoft

AI-ul ajută aici, și e corect să spunem asta. Poate parcurge rapid documentația, poate genera un diff pentru handlerul de webhook, poate propune un plan de test pe development store și poate schița modificările de schemă pentru câmpurile noi. Ce nu poate face este să decidă în locul tău dacă anularea trebuie afișată în dashboard, cum se mapează în WMS-ul tău și ce înseamnă pentru fluxul de reaprovizionare. Decizia și execuția rămân umane, iar media buyer-ul și omul de operațiuni sunt cei care știu cum arată recepția reală în depozit.

Pasul concret îl face ALLSoft Agency: ne uităm la stack-ul tău, verificăm ce versiune de API folosești, testăm handlerul de webhook și punem la punct sincronizarea stocului cu feed-ul și campaniile. Fără hype, fără cifre inventate, doar lucruri care se pot verifica.