PushCart: Same-Day Delivery Orders

Receive, confirm, and track Same-Day Delivery orders through the Cart API and webhooks.

🚧

Early Access (Beta)

Same-Day Delivery support for PushCart is in early access. Contact your Locally representative to request access before building against the endpoints and webhooks described here.

Overview

Same-Day Delivery (SDD) lets shoppers buy items that are in stock at a local store and have them delivered to their door the same day by a third-party courier (Uber, Roadie, DoorDash).

SDD orders flow through the same PushCart integration as pickup orders: Locally sends a webhook to your endpoint when the order is placed, you confirm or reject each item via the Cart API, and Locally automatically dispatches a courier once every item has been handled. Delivery progress is then pushed to your webhook endpoint in real time.

This article covers what is different about a delivery order. For the core PushCart workflow — API keys, webhook configuration, and confirming pickup orders — start with PushCart Integration.

Prerequisites

How a delivery order differs from a pickup order

  • The new-order webhook payload includes for_delivery: 1.
  • The cart's type is DELIVERY instead of HOLD or ORDER.
  • Get a Single Cart and Get All Carts responses include a delivery object with the courier, fees, delivery address, tracking link, and live driver info, and populate the cart-level delivery_status field.
  • Confirming the order triggers courier dispatch — there is no separate "initiate delivery" call, and you no longer need to pass a delivery_estimate_id on confirm.
  • In addition to the item-level webhooks you already receive, Locally sends cart-level delivery status webhooks as the courier picks up and delivers the order.

Lifecycle of a Same-Day Delivery Order

1. Order placed — webhook received

The shopper enters their delivery address at checkout, sees the live courier rate, and completes the order. Their card is authorized but not yet charged.

Locally then POSTs a payload to your webhook endpoint, one per item in the cart, just like a pickup order. Delivery orders are identified by for_delivery: 1:

{
  "store_id": 37175,
  "upc": "686487455948",
  "order_id": "EX2QL6",
  "status": "ordered",
  "for_ship_to_store": 0,
  "for_delivery": 1,
  "is_test": 0,
  "position_in_cart": 1,
  "total_in_cart": 1,
  "order_url": "https://www.locally.com/api/v2/cart/EX2QL6"
}

The webhook intentionally carries minimal data. Request the order_url (the Get a Single Cart endpoint) to retrieve the full order.

2. Retrieve the order

GET /api/v2/cart/{cart_hash} returns the standard cart payload plus a delivery object that is only present on DELIVERY carts:

{
  "properties": {
    "type": "DELIVERY",
    "hash": "EX2QL6",
    "delivery_status": "",
    "...": "..."
  },
  "customer": { "...": "..." },
  "store": { "...": "..." },
  "items": [ { "...": "..." } ],
  "delivery": {
    "delivery_type": "SDD",
    "carrier_id": 2,
    "status": 0,
    "carrier_name": "Uber",
    "customer_fee": "6.00",
    "carrier_fee": "6.00",
    "tracking_url": null,
    "carrier_tracking_number": null,
    "estimated_pickup_at": null,
    "estimated_dropoff_at": null,
    "actual_pickup_at": null,
    "actual_dropoff_at": null,
    "signature_url": null,
    "dropoff_photo_url": null,
    "scheduled_dispatch_at": null,
    "delivery_notes": "Gate code is 4482",
    "address": {
      "first_name": "John",
      "last_name": "Doe",
      "address_1": "2020 W Willow St",
      "address_2": "",
      "city": "Chicago",
      "state": "IL",
      "zip": "60647",
      "country": "US"
    },
    "driver": null
  }
}

Key fields:

FieldDescription
delivery.delivery_typeSDD for same-day delivery, CONVENTIONAL for standard shipping carriers.
delivery.carrier_idThe delivery carrier, named in carrier_name.
delivery.statusNumeric courier progress code. See Delivery status codes below.
delivery.customer_feeThe delivery fee the shopper paid at checkout.
delivery.carrier_feeThe fee charged by the courier.
delivery.tracking_urlLive tracking link. null until the courier accepts the job.
delivery.addressThe shopper's delivery address.
delivery.driverDriver name, vehicle, photo, and live lat/lng once a driver is assigned; null before that.
delivery.scheduled_dispatch_atIf the store scheduled the courier for later, the dispatch time.
delivery.signature_url / delivery.dropoff_photo_urlProof-of-delivery images, when the carrier supports them.

See Get a Single Cart for a complete delivery-order response.

3. Confirm or reject the items

Confirm each item the same way you confirm a pickup order, via Update a Cart Item:

POST /api/v2/cart/{cart_hash}/{upc}

{
  "status": "confirm",
  "message": "Confirmed! We will text you when your order is out for delivery."
}

Rules specific to delivery orders:

  • Confirm in full or reject. Partial-quantity confirmation (confirmed_qty) is not supported on delivery orders.
  • Confirming charges the shopper's card, exactly like a BOPIS pickup order.
  • No delivery_estimate_id required. Confirming a cart item now auto-triggers delivery creation — Locally uses the estimate captured at checkout, so you do not need to pass a delivery_estimate_id on confirm.
  • Respond quickly. The standard confirmation window applies, but shoppers expect same-day orders to move fast.

Send the courier now vs. later

By default, the courier is dispatched as soon as the order is fully confirmed. If the order needs prep time before it is ready for pickup — a bike that needs boxing, for example — include scheduled_dispatch_at (UTC, ISO 8601) with your confirmation and the courier will be dispatched at that time instead:

{
  "status": "confirm",
  "scheduled_dispatch_at": "2026-02-10T19:25:27Z"
}

Dispatch — immediate or scheduled — only happens while the store is open.

Expired delivery estimates

Courier quotes expire. If the quote from checkout is no longer valid when you confirm, the API responds with status: false and the message Delivery estimate has expired or is not valid. Orders in this state can still be confirmed from the Locally order management console in the store's Locally dashboard.

Automatic courier dispatch

Once every item in the cart has been confirmed or rejected (with at least one item confirmed), Locally creates the delivery and dispatches the courier automatically. There is no separate "initiate delivery" API call, and no delivery_estimate_id needs to be passed — confirming the item is all that is required. A driver heads to the store, and both the store and the shopper receive notifications at each step.

4. Track the delivery — webhooks

As the delivery progresses, Locally POSTs cart-level delivery webhooks to the same endpoint that receives your order webhooks. Unlike item webhooks, delivery webhooks have no upc — they describe the whole order:

{
  "order_id": "EX2QL6",
  "delivery_status": "pickup",
  "tracking_url": "https://delivery.uber.com/orders/62105936-e413-40d5-aecd-4c335c3cd3c2",
  "store_id": 37175,
  "for_delivery": 1,
  "is_test": 0,
  "estimated_dropoff_at": "2026-01-29 16:17:56",
  "courier": {
    "name": "TEST DRIVER",
    "vehicle_description": "Red Toyota Camry",
    "photo_url": "https://www.example.com/driver.jpg",
    "location": {
      "lat": 41.91136867,
      "lng": -87.67771437
    }
  },
  "order_url": "https://www.locally.com/api/v2/cart/EX2QL6"
}

The delivery_status values you will receive:

delivery_statusMeaningAdditional payload fields
pickupA courier has accepted the job and is heading to the store. May fire more than once as driver details update; includes the courier object once a driver is assigned.estimated_dropoff_at, courier
pickup_completeThe courier has picked up the package from the store.estimated_dropoff_at
deliveredThe package has been delivered to the shopper.signature_url, dropoff_photo_url
canceledThe delivery has been canceled.
📘

Delivery status webhooks are sent for native same-day delivery orders only. DoorDash Marketplace orders receive order and item webhooks but no delivery status webhooks, since DoorDash manages its own fulfillment. See Webhooks.

You can also poll Get a Single Cart at any time — the delivery.status code, delivery.driver location, and the cart-level delivery_status label all update as the delivery progresses.

5. Delivery complete

When the courier marks the delivery complete, the delivered webhook fires with the proof-of-delivery images (where the carrier supports them), and the item status advances to its fulfilled end state (see Cart Item Statuses).

Delivery status codes

The numeric delivery.status field returned by Get a Single Cart:

CodeStatusDescription
0PendingDelivery created; no courier dispatched yet.
1CanceledThe delivery was canceled.
2PickupA courier is en route to the store.
3Pickup CompleteThe courier has picked up the package.
4DropoffThe courier is arriving at the shopper's address.
5DeliveredThe delivery is complete.

The cart-level properties.delivery_status field carries a human-readable progress label for the same journey (for example Driver assigned or Delivery to destination complete), and is an empty string before the delivery process starts.

Cancellations and refunds

  • Before confirmation — if the shopper cancels or the item is out of stock, reject the item ("status": "reject") as you would on a pickup order. No charges apply.
  • After confirmation — the courier is already dispatched. The delivery can only be canceled before the driver arrives at the store, from the Locally order screen. If a delivery is canceled, your webhook endpoint receives a canceled delivery webhook.
  • Item refunds work exactly like pickup orders via the refund parameter on Update a Cart Item. Note that refunding an item does not cancel a dispatched courier — cancel the delivery too, or the store is still charged for the trip.

For the retailer-facing view of cancellations, returns, and delivery-fee refunds, see Set Up Same Day Delivery.