Confirm or cancel a fulfilment
The two mutations on this page apply only to projects where the external warehouse must validate each shipping before OMS ships it: the warehouse reports what was actually packed, and OMS books the carrier on that basis. This is a per-project choice, configured by Calicantus during onboarding.
The ids, SKUs, serial and batch numbers in these examples are placeholders — replace them with your own.
When the warehouse validates the shippings, OMS does not book the carrier as soon as the order is confirmed: the shipping waits, with fulfillmentStatus: pending and bookingStatus: pending (see Order and shipping statuses), for the warehouse to declare how the goods were packed. The warehouse closes this step with one of two mutations:
shippingFulfillmentConfirmwhen at least one item was packed, the whole shipping or a part of it.shippingFulfillmentCancelwhen nothing is packed and nothing will be shipped.
Each shipping accepts one declaration, with no follow-up calls: "partial" refers to the goods packed compared to the ones ordered, not to a confirmation in several steps. A shipping that is not waiting for the warehouse (booking already started, fulfilment not tracked, already declared) rejects both mutations with a BAD_REQUEST error.
Confirm the fulfilment
Use shippingFulfillmentConfirm to declare the parcels prepared and, when the shipping is not packed in full, the quantities packed per line. The mutation accepts a list of ShippingFulfillmentConfirmParcelInput and, optionally, a list of ShippingFulfillmentConfirmLineInput objects — their references list all the available fields. It returns the FulfillmentPacking created.
shippingId is the id of an entry of Order.shippings, and the shippingLineId values of lines are the id of that shipping's itemLines, the item lines the warehouse handles. Read them with the order query:
{
"data": {
"order": {
"id": "9347",
"shippings": [
{
"id": "9722",
"itemLines": [
{
"id": "26153",
"quantity": 2,
"orderLine": {
"sku": "SKU-1"
}
},
{
"id": "26154",
"quantity": 1,
"orderLine": {
"sku": "SKU-2"
}
}
]
}
]
}
},
"extensions": {
"queryComplexity": 9,
"bucketBalance": 9991,
"bucketRestoreRate": 100
}
}Field notes:
parcelsdescribes the parcels handed to the carrier:kind, dimensions in centimeters and netweightin grams, as forShippingParcel. At least one parcel is required and every value must be positive. They replace the parcels the shipping had.linesis optional: omit it to fulfil the whole shipping. When present, list the item lines you packed with thequantitypacked, which cannot exceed the line quantity: a line not listed has nothing packed (listing it withquantity: 0is equivalent), and the rest of a line's quantity stays unfulfilled.- The same
shippingLineIdcan appear more than once to declare differentserialNumberorbatchNumbervalues; a line with aserialNumbercovers one unit. AbatchNumberunknown to OMS is created.userNameis the operator who prepared the line, informational only. - If no item is packed at all, use the cancel mutation instead: a confirmation with every quantity at 0 is rejected.
After the confirmation the shipping's fulfillmentStatus is completed when every item was packed, partial otherwise; fulfilledQuantity and unfulfilledQuantity are set on each shipping line, and the booking proceeds with the parcels declared: bookingStatus moves from pending to ready, then confirmed when the shipping label (waybill) is generated.
Fulfil the whole shipping
Without lines, every item line is fulfilled in full.
mutation shippingFulfillmentConfirm {
shippingFulfillmentConfirm(
shippingId: "9724"
parcels: [{ kind: box, weight: 2500, length: 40, width: 30, height: 20 }]
) {
id
createdAt
shipping {
id
number
fulfillmentStatus
bookingStatus
parcels {
id
kind
weight
length
width
height
tailLiftRequired
}
}
lines {
id
quantity
serialNumber
userName
batch {
id
number
}
shippingLine {
id
quantity
fulfilledQuantity
unfulfilledQuantity
orderLine {
sku
}
}
}
}
}{
"data": {
"shippingFulfillmentConfirm": {
"id": "12",
"createdAt": "2026-09-03T12:53:22.814Z",
"shipping": {
"id": "9724",
"number": "1",
"fulfillmentStatus": "completed",
"bookingStatus": "pending",
"parcels": [
{
"id": "150",
"kind": "box",
"weight": 2500.0,
"length": 40.0,
"width": 30.0,
"height": 20.0,
"tailLiftRequired": false
}
]
},
"lines": [
{
"id": "37",
"quantity": 2,
"serialNumber": null,
"userName": null,
"batch": null,
"shippingLine": {
"id": "26157",
"quantity": 2,
"fulfilledQuantity": 2,
"unfulfilledQuantity": 0,
"orderLine": {
"sku": "SKU-1"
}
}
},
{
"id": "38",
"quantity": 1,
"serialNumber": null,
"userName": null,
"batch": null,
"shippingLine": {
"id": "26158",
"quantity": 1,
"fulfilledQuantity": 1,
"unfulfilledQuantity": 0,
"orderLine": {
"sku": "SKU-2"
}
}
}
]
}
},
"extensions": {
"queryComplexity": 31,
"bucketBalance": 9934,
"bucketRestoreRate": 100
}
}The bookingStatus in the response is still pending: the booking is picked up right after the confirmation, read the shipping again to follow it.
Fulfil part of the shipping
With lines, declare the quantity packed for each item line: here one of the two units of the first line is packed, the second line is packed in full. The unit not declared is not shipped with this shipping and cannot be declared in a second call.
mutation shippingFulfillmentConfirm {
shippingFulfillmentConfirm(
shippingId: "9725"
parcels: [{ kind: box, weight: 2500, length: 40, width: 30, height: 20 }]
lines: [
{ shippingLineId: "26159", quantity: 1 }
{ shippingLineId: "26160", quantity: 1 }
]
) {
id
shipping {
id
fulfillmentStatus
}
lines {
id
quantity
shippingLine {
id
quantity
fulfilledQuantity
unfulfilledQuantity
}
}
}
}{
"data": {
"shippingFulfillmentConfirm": {
"id": "13",
"shipping": {
"id": "9725",
"fulfillmentStatus": "partial"
},
"lines": [
{
"id": "39",
"quantity": 1,
"shippingLine": {
"id": "26159",
"quantity": 2,
"fulfilledQuantity": 1,
"unfulfilledQuantity": 1
}
},
{
"id": "40",
"quantity": 1,
"shippingLine": {
"id": "26160",
"quantity": 1,
"fulfilledQuantity": 1,
"unfulfilledQuantity": 0
}
}
]
}
},
"extensions": {
"queryComplexity": 31,
"bucketBalance": 9903,
"bucketRestoreRate": 100
}
}Track serial and batch numbers
When you track them, split a shipping line into one entry per serial number or batch: here the first line (2 ordered) is packed for one serialized unit, the second line is packed in full from a stock batch.
mutation shippingFulfillmentConfirm {
shippingFulfillmentConfirm(
shippingId: "9726"
parcels: [
{ kind: box, weight: 2500, length: 40, width: 30, height: 20 }
{ kind: box, weight: 1200, length: 30, width: 20, height: 15 }
]
lines: [
{
shippingLineId: "26161"
quantity: 1
serialNumber: "SN-0001"
batchNumber: "LOT-2026-09"
userName: "Mario Rossi"
}
{
shippingLineId: "26162"
quantity: 1
batchNumber: "LOT-2026-09"
userName: "Mario Rossi"
}
]
) {
id
shipping {
id
fulfillmentStatus
}
lines {
id
quantity
serialNumber
userName
batch {
id
number
}
shippingLine {
id
fulfilledQuantity
unfulfilledQuantity
}
}
}
}{
"data": {
"shippingFulfillmentConfirm": {
"id": "14",
"shipping": {
"id": "9726",
"fulfillmentStatus": "partial"
},
"lines": [
{
"id": "41",
"quantity": 1,
"serialNumber": "SN-0001",
"userName": "Mario Rossi",
"batch": {
"id": "44075",
"number": "LOT-2026-09"
},
"shippingLine": {
"id": "26161",
"fulfilledQuantity": 1,
"unfulfilledQuantity": 1
}
},
{
"id": "42",
"quantity": 1,
"serialNumber": null,
"userName": "Mario Rossi",
"batch": {
"id": "44075",
"number": "LOT-2026-09"
},
"shippingLine": {
"id": "26162",
"fulfilledQuantity": 1,
"unfulfilledQuantity": 0
}
}
]
}
},
"extensions": {
"queryComplexity": 31,
"bucketBalance": 9872,
"bucketRestoreRate": 100
}
}Cancel the fulfilment
Use shippingFulfillmentCancel when no item of the shipping is packed: it takes the shippingId only (the id of the shipping in Order.shippings) and returns the updated Shipping.
After the cancellation the shipping has fulfillmentStatus: cancelled, no parcels and no fulfillmentPacking, and accepts no further declaration.
mutation shippingFulfillmentCancel {
shippingFulfillmentCancel(shippingId: "9720") {
id
number
fulfillmentStatus
bookingStatus
status
parcels {
id
}
lines {
id
quantity
fulfilledQuantity
unfulfilledQuantity
}
fulfillmentPacking {
id
}
}
}{
"data": {
"shippingFulfillmentCancel": {
"id": "9720",
"number": "1",
"fulfillmentStatus": "cancelled",
"bookingStatus": "pending",
"status": null,
"parcels": [],
"lines": [
{
"id": "26149",
"quantity": 2,
"fulfilledQuantity": 0,
"unfulfilledQuantity": 0
},
{
"id": "26150",
"quantity": 1,
"fulfilledQuantity": 0,
"unfulfilledQuantity": 0
}
],
"fulfillmentPacking": null
}
},
"extensions": {
"queryComplexity": 15,
"bucketBalance": 9938,
"bucketRestoreRate": 100
}
}