Applies to: Orders API
Learn how to create, update, cancel, and split an order fulfillment.
A seller might add fulfillment information to an order when it's created or updated. They can use Square products or your Orders API-integrated application to manage their fulfillments.
Did you know?
If you want to track the progress of order fulfillments that are managed in a Square product, you should subscribe to Orders webhooks for notification of fulfillment events triggered outside of your application.
The Orders API stores fulfillment information in the Order.fulfillments field (an array of Fulfillment objects). Each Fulfillment
includes the following:
uid
- A Square-assigned unique identifier.type
- The type of fulfillment.state
- Initially, the fulfillment state isPROPOSED
.- Fulfillment details - Depending on the
type
, fulfillment details are stored in pickup_details, shipment_details, or delivery_details.
The Orders API supports fulfillments of these types:
DELIVERY
(Beta)PICKUP
SHIPMENT
(Beta)
- One fulfillment limit - Developers can add only one fulfillment to an order using the Orders API, either during or after creation.
- No fulfillment splitting - All items for an order created with the Orders API must be fulfilled at the same location.
- Limited delivery fulfillment support - Any order you create with the DELIVERY fulfillment type is not available to a seller and not shown in the Square Point of Sale unless you have a formal partnership agreement with Square. Request Beta access by completing the participation survey.
- Only paid orders are visible - Orders with fulfillments appear on Square products (such as the Square Dashboard and Point of Sale application) only after they're paid for. Sellers can then manage fulfillments for these orders using these Square products.
- Immutable fields - Most fulfillment fields are immutable based on the fulfillment
state
. Editable fields include:state
(if the order is being managed through a developer's application).pickup_details
fields, such as thepickup_at
ornote
field.recipient
field, such asaddress
orphone_number
.shipment_details
fields, such astracking_number
ortracking_url
.
A seller might create orders using your application but can also create orders with Square products such as Square Online. In that case, orders that your application retrieves might have multiple fulfillments. For information about how a seller can create a multiple-fulfillment order using Square, see Manage cross location orders with Square for Retail.
Note
If your application retrieves a DELIVERY
fulfillment order, it cannot access fulfillment delivery_details unless you are a Square partner developer and have signed up for the closed DELIVERY
Beta. For more information, see DELIVERY type fulfillment.
If your application lets sellers see the state of any order fulfillments in their Square account, then it should handle cases where the Order.fulfillments
array contains multiple items. While your application can only create single-fulfillment orders, it has access to fulfillment orders created by Square applications.
The following Order
fragment shows a SHIPMENT
Fulfillment:
{
"order": {
"id": "uuVIIBP9Nl8L7xq6MJQayNuo8LdZY",
"location_id": "S8GWD5R9QB376",
"line_items": [
…
],
"fulfillments": [
{
"type": "SHIPMENT",
"shipment_details": {
"recipient": {
"display_name": "John Doe"
}
}
}
]
}
}
The recipient.display_name
is the only shipment_details field required when a fulfillment is created. Other shipment_details
fields are optional: carrier
, shipping_note
, shipping_type
, tracking_number
, and tracking_url
.
As a SHIPMENT
fulfillment order moves through stages, the fulfillment state is updated and corresponding timestamps are set:
in_progress_at
- state changes toRESERVED
packaged_at
- state changes toPREPARED
shipped_at
- state changes toCOMPLETED
canceled_at
- state changes toCANCELED
failed_at
- state changes toFAILED
This Order
fragment shows a PICKUP
Fulfillment scheduled for delivery ASAP but with a 30 minute prep time. Note the pickup_at
time is 30 minutes after the order is created:
{
"order": {
"id": "sfADX2Xqb8F4uZaFuAp3xlShefbZY",
"location_id": "S8GWD5R9QB376",
"line_items": [
…
],
"fulfillments": [
{
"type": "PICKUP",
"state": "PROPOSED",
"uid": "pickup1",
"pickup_details": {
"schedule_type": "ASAP",
"prep_time_duration": "PT30M15S",
"recipient": {
"customer_id": "{{customer_id}}"
}
}
}
],
}
}
The pickup_at
and recipient.display_name
fields are the only pickup_details fields required when creating a fulfillment. The following apply for the other pickup_details
fields:
- The
schedule_type
value determines the following:- If set to
SCHEDULED
,pickup_at
is required. - If set to
ASAP
,prep_time_duration
orpickup_at
is required.
- If set to
- These fields can only be set while the order fulfillment
state
isPROPOSED
:expires_at
,auto_complete_duration
,prep_time_duration
, andschedule_type
.
A scheduled order does not move to the 'Active' tab in Order Manager (and show up on a KDS or print from kitchen printers) until pickup time minus prep time. Although prep_time_duration
is not required for the SCHEDULED
type, Square recommends that your application sets the value. If a prep time is not provided, a seller using a KDS or kitchen printer might not know a SCHEDULED
pickup is actionable until the time the buyer is supposed to arrive to pick up the order.
If the schedule_type
is ASAP
and the prep_time_duration
is set then Square sets the pickup_at
time to now plus prep_time_duration
. If your application sets pickup_at
for an ASAP
pickup, prep_time_duration
is ignored even if you've set that value too.
As a PICKUP
fulfillment order moves through stages, the fulfillment state is updated and corresponding timestamps are set:
accepted_at
- The state changes toRESERVED
ready_at
- The state changes toPREPARED
pick_up_at
- The state changes toCOMPLETED
.canceled_at
- The state changes toCANCELED
rejected_at
- The state changes toFAILED
This is a restricted (closed) Beta. Request Beta access by completing the participation survey.
Beta access to the DELIVERY
fulfillment type is for use cases other than performing deliveries on behalf of sellers. Developers seeking to perform deliveries on behalf of sellers need a formal partnership agreement. To become an app partner, submit a partnership request.
Important
Requests to create a DELIVERY
fulfillment order succeed with a 200 response even if you don't have a partnership agreement and are enrolled in the delivery beta program. However, the delivery order you create cannot be accessed by a seller and does not appear in the Square Order Manager.
This Order
fragment shows a DELIVERY
fulfillment:
{
"order":{
"id":"MgVVrx8GhOy4K7LO7LtYwgM3RUaZY",
"location_id":"7WQ0KXC8ZSD90",
"line_items":[
{
}
],
"fulfillments":[
{
"uid":"uYJmomsp8OjA2iY8PZR2IC",
"type":"DELIVERY",
"state":"PROPOSED",
"delivery_details":{
"recipient":{
"display_name":"John Doe",
"phone_number":"2065129261",
"address":{
"address_line_1":"111 Maple",
"locality":"Seattle"
}
},
"deliver_at":"2022-05-25T20:59:33.123Z"
}
}
]
"state":"OPEN",
"version":1,
}
}
Note the following about delivery_details:
The following information is required when creating a delivery fulfillment:
recipient
details - Thedisplay_name
,address
, andphone_number
are required if there's no third-party managing delivery (managed_delivery
is set tofalse
).schedule_type
- It can be set toSCHEDULED
(default) orASAP
.deliver_at
- Ifschedule_type
is set toASAP
, this field is automatically set to the time the order is created plus theprep_time_duration
. This field is required whenschedule_type
is set toSCHEDULED
.
Applications can provide optional delivery_detail
information, such as:
prep_time_duration
. The time it takes to prepare and deliver the fulfillment.- A combination of
deliver_at
anddelivery_window_duration
identifying the order delivery window. - Courier information (such as
courier_provider_name
,courier_support_phone_number
, and the combination ofcourier_pickup_at
andcourier_pickup_window_duration
identifying the courier pickup window). - Other information (such as optional drop-off notes and whether the delivery is a no-contact delivery).
For a delivery managed by a third party:
- Set the
managed_delivery
field totrue
. This makes the recipient information optional, such asdisplay_name
andaddress
. - The
courier_provider_name
andcourier_support_phone_number
fields are required.
As an order moves through stages of fulfillment, the state of the fulfillment is updated and corresponding timestamps are set:
delivery_details.in_progress_at
- The state changes toRESERVED
delivery_details.ready_at
- The state changes toPREPARED
delivery_details.canceled_at
- The state changes toCANCELED
delivery_details.rejected_at
- The state changes toFAILED
delivery_details.completed_at
- The state changes toCOMPLETED
.
Applications can create an order with fulfillment or first create an order and later update the order to include fulfillment.
This example is a CreateOrder request that creates an order for four sandwiches. The order includes fulfillment details. The order type is a PICKUP
order and the customer, John Doe, has selected curbside pickup at a specific time.
Create order
The following is an example response fragment:
{ "order": { "id": "sfADX2Xqb8F4uZaFuAp3xlShefbZY", "location_id": "S8GWD5R9QB376", "line_items": [ { "uid": "U0PzEdJgoOPWE7AxvCRldC", "quantity": "4", "name": "Sandwich", "base_price_money": { "amount": 1500, "currency": "USD" }, "note": "ad hoc item", "gross_sales_money": { "amount": 6000, "currency": "USD" }, … ], "fulfillments": [ { "uid": "VnDwb1Yu42mMjrPEWHLYW", "type": "PICKUP", "state": "PROPOSED", "pickup_details": { "pickup_at": "2022-02-12T23:00:00.000Z", "recipient": { "display_name": "John Doe", "phone_number": "111-111-1111" }, "is_curbside_pickup": true } } ], … } }
In this example, you create an order and then update the order to add fulfillment. Note that you cannot add a fulfillment if the order state
is COMPLETED
.
Call
CreateOrder
to create an order without a fulfillment.Create order
Call
UpdateOrder
to update the order and add fulfillment details. The example adds thePICKUP
type fulfillment to the order.Update order
Note
To view the fulfillments for an existing order, call RetrieveOrder. The fulfillments appear in the Order.fulfillments object of the RetrieveOrder response.
In the current implementation, there are limitations to updating fulfillments using the Orders API. For more information, see Guidelines and limitations.
Note
If you're attempting to update a fulfillment to set its state to COMPLETE
, all payments on the order must already be complete. For information about completing payments on a order, see Using the Orders API PayOrder endpoint.
Suppose you created an order for an ad hoc item. The following UpdateOrder
example updates the fulfillment state, recipient display name, pickup detail note, and recipient display name:
Update order
The following is an example response fragment:
{ "order": { "id": "sfADX2Xqb8F4uZaFuAp3xlShefbZY", "location_id": "S8GWD5R9QB376", "line_items": [ { … } ], "fulfillments": [ { "uid": "VnDwb1Yu42mMjrPEWHLYW", "type": "PICKUP", "state": "PREPARED", "pickup_details": { "pickup_at": "2022-02-12T23:00:00.000Z", "note": "updated note", "accepted_at": "2022-02-26T00:24:07.316Z", "ready_at": "2022-02-26T00:24:07.316Z", "recipient": { "display_name": "Jane Doe", "phone_number": "111-111-1111" }, "is_curbside_pickup": true } } ], … "version": 2, } }
A DELIVERY
type fulfillment completes when the items are delivered to the buyer. However, there are times when a seller (or deliver service) cancels the fulfillment or the fulfillment fails to complete. The following are the suggested best practices for an application to update an order as the DELIVERY
type fulfillment progresses:
Fulfillment item is delivered
Before attempting to set a fulfillment.state
to COMPLETED
, the order must be paid for.
- If the
fulfillment.state
isn'tCOMPLETED
:- Set
FulfillmentDeliveryDetails.delivered_at
to the timestamp when delivery occurred. - Set
fulfillment.state
toCOMPLETED
. - Set
order.state
toCOMPLETED
if no other fulfillments are pending and all payments on the order have been completed.
- Set
- If the
fulfillment.state
isCOMPLETED
(this can happen if a seller marks it asCOMPLETED
after they hand off the goods to the delivery service but before the delivery is completed):- The application can update
delivered_at
after a fulfillment is marked asCOMPLETED
but before the orderstate
isCOMPLETED
. Ifdeliver_at
cannot be updated, the application might save thedelivered_at
timestamp as a note in theorder.fulfillments.delivery_details.note
field. - Set
order.state
toCOMPLETED
if no other fulfillments are pending and all payments on the order have been completed.
- The application can update
Fulfillment is canceled by the seller or delivery service
Specify the cancellation reason in the
FulfillmentDeliveryDetails.notes
field.Set
order.state
toCOMPLETED
if no other fulfillments are pending.Set
order.state
toCOMPLETED
orCANCELED
. Note that you cannot setorder.state
toCANCELED
if:- A completed payment exists on the order.
- The order contains a completed fulfillment. The seller needs to perform a refund in Square Point of Sale if necessary after the order is
COMPLETED
.
Note that
order.state
cannot be set toCANCELED
if the order contains a completed fulfillment. The seller needs to perform a refund in Square Point of Sale if necessary after the order isCOMPLETED
.
Fulfillment fails to complete
Specify a reason why the fulfillment failed in the
FulfillmentDeliveryDetails.notes
field.Set
fulfillment.state
toFAILED
.Set
order.state
toCOMPLETED
if all payments on the order have been completed.Note that
order.state
cannot be set toCANCELED
if the order contains a completed fulfillment. The seller needs to perform a refund in Square Point of Sale if necessary after the order isCOMPLETED
.
You cannot delete a fulfillment from an order. You can only cancel a fulfillment using the UpdateOrder
endpoint as shown:
curl https://connect.squareupsandbox.com/v2/orders/{ORDER_ID} \
-X PUT \
-H 'Square-Version: 2022-09-21' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-H 'Content-Type: application/json' \
-d '{
"idempotency_key": "{UNIQUE_KEY}",
"order": {
"version": 2,
"fulfillments": [
{
"uid": "{FULFILLMENT_UID}",
"state": "CANCELED"
}
]
}
}'
In the request, provide the Order
object with the following information in the request body:
- The
version
of the order. - The
fulfillments
array identifying the fulfillment to be canceled. Provide the fulfillment UID being updated and set the value ofstate
toCANCELED
.
Did you know?
An order cannot be canceled if its fulfillments are not in a CANCELED
state.
A seller might split a fulfillment using Square products. The Orders API can retrieve these split fulfillments. For example, the Order.fulfillments object includes two fields (entries
and line_item_application
) that applications can use to determine which line items belong to which fulfillment.