Support Weighted Items via Merchant Pick
Overview
The Mx Pick Weighted Items feature adds support for weighted line items — products sold by weight rather than by a fixed unit price (for example, loose produce, deli items, and bulk goods). Adopting this feature requires changes at two points in the order lifecycle:
- Order transmit — DoorDash will include weighted item data (estimated quantity and purchase type) in the inbound order payload so your integration knows which items require weight reporting.
- Order adjustment — After picking, your integration reports the actual measured weight back to DoorDash via the existing Order Adjustment API so the final price can be calculated correctly.
New fields are added to both the order transmit body and the PATCH /marketplace/api/v1/orders/{order_id}/adjustment endpoint. All new fields are optional for non-weighted items — existing integrations are unaffected until weighted items appear in an order.
Prerequisites
Reach out to your technical account manager to confirm your integration is enabled for Mx Pick Weighted Items before testing.
Order flow
Adopting this feature requires changes at both ends of the order lifecycle:
- Order transmit — DoorDash includes
purchase_typeon every line item and, forMEASUREMENTitems, an estimatedrequested_quantitywhen dispatching the order to the merchant. The merchant must read these fields to know which items are weighted and what the customer's requested estimate is. - Order adjustment — After picking, the merchant reports the actual measured weight back to DoorDash via the adjustment endpoint. DoorDash uses this to calculate the final charge.
Both steps are required. An integration that only handles the adjustment without reading the inbound weighted item fields will not have the data needed to pick correctly.
Inbound order payload changes
Weighted line items in the order transmit body now include purchase_type. MEASUREMENT items additionally include requested_quantity — the customer's initial estimated weight at order time. It is a single { quantity, unit } weight object. This is not the final picked weight; the merchant reports the picked weight back via fulfill_quantity on the adjustment request.
UNIT_TO_MEASUREMENT and UNIT items carry only purchase_type — no estimated quantity is sent on transmit.
The standard line-item fields you already receive (id, line_item_id, merchant_supplied_id, name, price, quantity, extras, …) are unchanged — the two weighted fields simply appear alongside them. Note that the integer quantity is the number of units ordered (for example, 3 bananas) and is independent of requested_quantity, which is the estimated weight of a MEASUREMENT item. The example below shows three line items — one of each purchase_type — within the order's categories array (some standard fields are trimmed for brevity):
{
"categories": [
{
"merchant_supplied_id": "DELI",
"name": "Deli",
"items": [
{
"id": "7117374961",
"line_item_id": "83632867-9cf6-4657-a48f-9504cc70864a",
"merchant_supplied_id": "DELI-1001",
"name": "Sliced Deli Turkey (per lb)",
"price": 1699,
"quantity": 1,
"purchase_type": "MEASUREMENT",
"requested_quantity": { "quantity": 0.75, "unit": "lb" }
}
]
},
{
"merchant_supplied_id": "PRODUCE",
"name": "Produce",
"items": [
{
"id": "7117374962",
"line_item_id": "94b653e4-e394-4330-a714-43e764abe843",
"merchant_supplied_id": "PRODUCE-2002",
"name": "Banana (each)",
"price": 45,
"quantity": 3,
"purchase_type": "UNIT_TO_MEASUREMENT"
}
]
},
{
"merchant_supplied_id": "GROCERY",
"name": "Grocery",
"items": [
{
"id": "7117374963",
"line_item_id": "c45b3754-03b2-4da6-ae7f-164d5f8f587b",
"merchant_supplied_id": "GROCERY-3003",
"name": "Sparkling Water 12-pack",
"price": 599,
"quantity": 2,
"purchase_type": "UNIT"
}
]
}
]
}
| Field | Appears on | Meaning |
|---|---|---|
| purchase_type | Every line item | How the item is priced and fulfilled — UNIT, MEASUREMENT, or UNIT_TO_MEASUREMENT (see purchase_type values) |
| requested_quantity | MEASUREMENT items only | The customer's estimated weight at order time — a single { quantity, unit } object using the same weight units as continuous_quantity |
fulfill_quantity is an adjustment-request field only and is never present in the order transmit body.
Endpoint
PATCH https://openapi.doordash.com/marketplace/api/v1/orders/{order_id}/adjustment
| Property | Value |
|---|---|
| Method | PATCH |
| Auth | Provider API key (unchanged) |
| Content-Type | application/json |
| Idempotency | No duplicate-submission deduplication. A no-op or invalid-state adjustment (e.g. order not confirmed or already cancelled) is rejected with 400 |
New Request Fields
The following fields are added to the existing AdjustedItem object. All are optional for non-weighted items.
| Field | Type | Required | Description |
|---|---|---|---|
| purchase_type | enum | Required when sending weighted data | How the line item is priced — see purchase_type values |
| fulfill_quantity | FulfillQuantity[] | Required for MEASUREMENT and UNIT_TO_MEASUREMENT | Picker-reported actual weight — see fulfill_quantity |
purchase_type Values
purchase_type indicates how a line item is priced and determines what weight data DoorDash expects.
| Value | Meaning | fulfill_quantity shape |
|---|---|---|
| UNIT | Sold by discrete count only — not weighted | Must NOT be sent |
| MEASUREMENT | Sold purely by weight (for example, loose produce per lb) | Each entry: continuous_quantity only |
| UNIT_TO_MEASUREMENT | Sold in discrete units each weighed individually (for example, whole fish, deli packs) | Each entry: both continuous_quantity AND discrete_quantity |
purchase_type must match what DoorDash has on record for that line item. Sending weight data (fulfill_quantity) on a UNIT item is rejected with a 409. Omitting fulfill_quantity on a MEASUREMENT or UNIT_TO_MEASUREMENT item is rejected with a 422.
fulfill_quantity
An array of fulfillment weight readings. For UNIT_TO_MEASUREMENT, send one entry per picked unit. For MEASUREMENT, one or more entries are valid (multiple entries are summed for the tolerance check).
FulfillQuantity object
{
"continuous_quantity": {
"quantity": 1.35,
"unit": "lb"
},
"discrete_quantity": {
"quantity": 1,
"unit": "ea"
}
}
continuous_quantity
Reports the measured weight of this reading.
| Field | Type | Required | Description |
|---|---|---|---|
| quantity | number | Yes | Positive weight value |
| unit | enum | Yes | Weight unit — see accepted values below |
Accepted weight units:
| Value | Name |
|---|---|
| lb | Pound (canonical) |
| lbs | Pound (alias, accepted for compatibility) |
| oz | Ounce |
| kg | Kilogram |
| g | Gram |
discrete_quantity
Reports the count of physical units in this reading.
| Field | Type | Required | Description |
|---|---|---|---|
| quantity | integer | Yes | Must be >= 1 |
| unit | enum | Yes | Discrete unit — see accepted values below |
Accepted discrete units:
| Value | Name |
|---|---|
| ea | Each |
| qty | Quantity |
| package | Package |
| bag | Bag |
| bunch | Bunch |
| box | Box |
| tray | Tray |
| bouquet | Bouquet |
| pot | Pot |
UNIT_TO_MEASUREMENT constraint
For UNIT_TO_MEASUREMENT items, send one fulfill_quantity entry per picked unit. The sum of all discrete_quantity.quantity values across entries must equal the top-level quantity field on the item. Mismatches are rejected with 422.
Weighted Substitutions
When substituting a weighted item, include purchase_type and fulfill_quantity on the substituted_item object.
| Field | Type | Required | Description |
|---|---|---|---|
| merchant_supplied_id | string | Yes | Merchant's identifier for the substitute item |
| name | string | No | Display name of the substitute |
| price | integer (cents) | No | Unit price of the substitute |
| quantity | integer | No | Number of substitute units |
| purchase_type | enum | Required for weighted substitutes | Must match the substitute item's pricing type |
| fulfill_quantity | FulfillQuantity[] | Required for MEASUREMENT / UNIT_TO_MEASUREMENT substitutes | Actual picked weight of the substitute |
The customer-side weight tolerance check does not apply to substitutions, because the customer did not specify a target weight for the substitute item.
Example Requests
UNIT_TO_MEASUREMENT: Two packs of salmon, each weighed individually
{
"items": [
{
"line_item_id": "94b653e4-e394-4330-a714-43e764aergjn",
"adjustment_type": "ITEM_UPDATE",
"quantity": 2,
"purchase_type": "UNIT_TO_MEASUREMENT",
"fulfill_quantity": [
{
"continuous_quantity": { "quantity": 1.32, "unit": "lb" },
"discrete_quantity": { "quantity": 1, "unit": "ea" }
},
{
"continuous_quantity": { "quantity": 1.47, "unit": "lb" },
"discrete_quantity": { "quantity": 1, "unit": "ea" }
}
]
}
]
}
The sum of discrete_quantity (1 + 1 = 2) matches the top-level quantity of 2.
MEASUREMENT: Loose deli turkey, reported as a single weight
{
"items": [
{
"line_item_id": "b3c12a88-0011-42de-b901-aabbcc001122",
"adjustment_type": "ITEM_UPDATE",
"quantity": 1,
"purchase_type": "MEASUREMENT",
"fulfill_quantity": [
{
"continuous_quantity": { "quantity": 0.73, "unit": "lb" }
}
]
}
]
}
ITEM_SUBSTITUTE with a weighted substitute
{
"items": [
{
"line_item_id": "94b653e4-e394-4330-a714-43e764ab113",
"adjustment_type": "ITEM_SUBSTITUTE",
"substituted_item": {
"merchant_supplied_id": "item-179",
"name": "Organic Gala Apple",
"price": 350,
"quantity": 1,
"purchase_type": "MEASUREMENT",
"fulfill_quantity": [
{
"continuous_quantity": { "quantity": 0.82, "unit": "lb" }
}
]
}
}
]
}
Mixed: one weighted item and one non-weighted removal
{
"items": [
{
"line_item_id": "aabbcc00-1234-5678-9abc-def000000001",
"adjustment_type": "ITEM_UPDATE",
"quantity": 1,
"purchase_type": "MEASUREMENT",
"fulfill_quantity": [
{
"continuous_quantity": { "quantity": 0.55, "unit": "kg" }
}
]
},
{
"line_item_id": "aabbcc00-1234-5678-9abc-def000000002",
"adjustment_type": "ITEM_REMOVE"
}
]
}
Response Codes
| HTTP Code | Meaning | When it occurs |
|---|---|---|
| 202 Accepted | Success | Adjustment accepted and queued for processing |
| 400 Bad Request | Order state error | Order is not yet confirmed, has been cancelled, the adjustment is a no-op, or the store is not enabled for order adjustments |
| 401 Unauthorized | Auth failure | Missing or invalid API key |
| 403 Forbidden | Permission denied | Caller does not have access to this order |
| 404 Not Found | Unknown identifier | Order, line item, or option ID does not exist |
| 409 Conflict | Weighted-item type conflict | fulfill_quantity sent for a line item DoorDash priced as non-weighted (UNIT) |
| 422 Unprocessable Entity | Weighted-item validation failure | Structural issue — including weighted data omitted for a MEASUREMENT or UNIT_TO_MEASUREMENT item. See Validation Rules |
| 429 Too Many Requests | Rate limited | Request rate exceeded |
| 500 Internal Server Error | Unexpected error | Contact DoorDash support |
409 and 422 are new codes introduced for weighted items. They are only returned when purchase_type or fulfill_quantity is present in the request. Existing integrations that do not send these fields will never receive these codes.
All non-202 responses include a JSON error body:
{ "message": "Invalid weighted-item adjustment payload" }
Validation Rules
| Rule | Code |
|---|---|
purchase_type = UNIT and non-empty fulfill_quantity sent | 409 |
purchase_type = MEASUREMENT or UNIT_TO_MEASUREMENT and fulfill_quantity absent or empty | 422 |
purchase_type does not match DoorDash's record for the line item | 422 |
MEASUREMENT entry contains discrete_quantity | 422 |
UNIT_TO_MEASUREMENT entry missing continuous_quantity or discrete_quantity | 422 |
Sum of discrete_quantity across entries does not equal item quantity (UNIT_TO_MEASUREMENT) | 422 |
continuous_quantity.unit not in the accepted weight unit list | 422 |
discrete_quantity.unit not in the accepted discrete unit list | 422 |
continuous_quantity.quantity is less than or equal to 0 | 422 |
discrete_quantity.quantity is less than 1 | 422 |
| Picked weight outside the allowed tolerance (applies to MEASUREMENT and UNIT_TO_MEASUREMENT ITEM_UPDATEs with a recorded estimated weight; not applied to substitutions) | 422 |