Skip to main content

Order Adjustments

Overview​

When the kitchen cannot fulfill an order exactly as placed, your POS can ask Stream to adjust it: remove a line item, reduce its quantity, or substitute another item (a size downgrade counts as a substitution). Stream validates the request immediately, pushes the change to the DSP, and reports the outcome back to your Handle Order endpoint.

note

POS-initiated adjustments are opt-in and enabled per merchant. Contact Stream to enable them. Until then, requests are rejected with 403 feature_disabled.

Not supported: adding items, refund amounts, and modifier-level changes.

DSP support​

DSPRemovalQuantity reductionSubstitution
DoorDashYesYesNo
Uber EatsYesYesNo
GlovoYesYesYes
Other DSPsNoNoNo

A DSP can still decline an adjustment it normally supports. Uber Eats, for example, may ask the customer to confirm. Stream then reports the result asynchronously (see Results).

Requesting an Adjustment​

Send an order.adjustment.requested event to the Handle Webhook Event endpoint, signed like every other webhook event.

{
"type": "order.adjustment.requested",
"object": {
"order_id": "8c1f0f3e2d0b4c6a",
"location_id": "location-456",
"adjustments": [
{ "_id": "fries_line_id", "adjustment_type": "removal" },
{
"_id": "burger_line_id",
"adjustment_type": "quantity_update",
"new_quantity": 1
},
{
"_id": "soda_line_id",
"adjustment_type": "substitution",
"substitution": {
"provider_id": "water-sku",
"name": "Water",
"quantity": 1
}
}
]
}
}
  • order_id: the Stream order id, sent as idempotency_key on order.created.
  • location_id: your provider location id for the order.
  • adjustments[]._id: the line item's _id from order.created (line_items[]._id). Each line item may appear at most once.
  • new_quantity: required for quantity_update. It must be at least 1 and lower than the current quantity. To go to zero, use removal.
  • substitution: required for substitution. Give the replacement's provider_id and quantity; name is optional. The line keeps its original price.

An order can be adjusted once. Combine every change into a single request.

Validation Responses​

Stream answers synchronously. A 2xx means the request was accepted and is being sent to the DSP. Rejections return a JSON body with a machine-readable code:

{
"statusCode": 409,
"error": "Conflict",
"code": "order_not_modifiable",
"message": "Order is not modifiable in status ready_for_pickup"
}
HTTPcodeWhen
400—Malformed payload (missing fields, unknown adjustment_type, duplicate _id)
403feature_disabledThe merchant is not enabled for POS-initiated adjustments
404order_not_foundNo order with this order_id at this location_id
409order_not_modifiableThe order is not pending/in_progress, or it was canceled
409order_already_adjustedThe order was already adjusted
400unsupported_by_dspThe DSP does not accept POS adjustments, or does not support substitutions
400invalid_adjustment_id not on the order or matching more than one line, new_quantity too high, or every item removed

Results​

Once the DSP responds, Stream sends one of these events to your Handle Order endpoint:

  • order.adjusted: the full, updated order, with adjusted: true and applied_adjustments listing what the DSP accepted. Each applied adjustment carries the line item _id and, for substitutions, the substitution.
  • order.adjustment.failed: nothing was changed on the order.
{
"type": "order.adjustment.failed",
"object": {
"order_id": "8c1f0f3e2d0b4c6a",
"location_id": "location-456",
"code": "dsp_rejected",
"reason": "Order already picked up",
"adjustments": [{ "_id": "fries_line_id", "adjustment_type": "removal" }]
}
}
codeMeaning
unsupported_by_dspThe DSP does not support this adjustment for this order
dsp_rejectedThe DSP refused the adjustment
dsp_errorThe DSP could not be reached or returned an unexpected error
order_not_modifiableThe order changed after the request was accepted (e.g. canceled)

A failed adjustment does not use up the order's one adjustment. You may send a corrected request.