Skip to main content

Implement delivery with an integrated shopper experience

Learn how to implement a basic delivery workflow that supports having an in-store shopper who uses the Instacart Shopper app. You can try out this tutorial in your development environment.

note

While this tutorial shows you how to create an order, the order you create is sent to a development version of the Fulfillment engine. You don't need to worry about groceries showing up at the example address we use!

To support your development efforts, this tutorial also includes tips and best practices to consider when you implement the delivery workflow in a production environment.

  1. Before you begin
  2. Find store locations near the customer
  3. Create a Connect user account
  4. Fill a cart
  5. Understand changes required in the checkout process
  6. Reserve a time slot for delivery
  7. Create a delivery order
  8. What happens to an order in a production environment?
  9. After an order is completed
  10. Summary

Before you begin

For this tutorial, you need the following items:

If store locations and catalog items are not yet in your development environment, contact your Instacart representative.

Variables used in this tutorial

The following variables are used in requests in this tutorial. When you see a variable, substitute them with values that work in your development environment.

VariableDescription
<instacart_development_domain>The domain of your assigned Instacart development server.
<token>The generated access token.
<item_upc>The UPC number of an item in your development store that you can add a cart.
<location_code>After you find stores, select one to use in this tutorial. You'll need this value when you reserve a time slot and create an order.
<service_option_id>After you find available time slots, select one to use in this tutorial. You'll need this value when you reserve a time slot.
<service_option_hold_id>After you reserve the time slot, note the ID. You'll need this value when you create the order.

The responses in this tutorial show sample values in place of the variables. The responses that are returned in your environment should have a similar format to the example responses. If you are interested in other possible responses, see the API documentation.

Find store locations near the customer

By default, if a store location is defined in your environment, a customer can request delivery from it. If your organization decided to make some of the stores pickup only, the store has the flag pickup_only set to true. Pickup only stores are omitted from the response.

Find the stores offering delivery near the specified address. In the request, substitute your values for the variables <instacart_development_domain> and <token>. If you don't have stores near this address, substitute an address that you know is close to one of your stores.

curl --request POST \
--url 'https://<instacart_development_domain>/v2/fulfillment/stores/delivery' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"find_by": {
"address_line_1": "50 Beale St",
"postal_code": "94105"
}
}'

The response contains the array of store locations near the address.

{
"stores": [
{
"name": "Example Location 1",
"location_code": "123-4567",
"flags": {
"alcohol": true,
"pickup": false,
"pickup_only": false
}
},
{
"name": "Example Location 2",
"location_code": "123-4678",
"flags": {
"alcohol": true,
"pickup": false,
"pickup_only": false
}
},
{
"name": "Example Location 3",
"location_code": "123-4789",
"flags": {
"alcohol": false,
"pickup": false,
"pickup_only": false
}
}
],
"is_partial": false
}

From the response returned in your development environment, choose a store to use in this tutorial. You'll substitute the location code for the variable <location_code> in requests.

Production environment tip

When you get the list of stores, you can either choose a store location for the customer or allow the customer to select a store location where they want to shop. You can think of the selected store as the inventory store. If your retailer site passes this store location when it requests a time slot or creates an order, the store location is also likely to be the fulfillment store.

Create a Connect user account

The user account contains the minimum information required by Instacart to create and fulfill an order. The account must have at least a unique user ID and the customer's first name. The user ID is defined by you, but it must be unique for all retailer customers. For example, you might choose user names or loyalty card IDs.

Create the user account. In the request, substitute your values for the variables <instacart_development_domain> and <token>.

curl --request POST \
--url 'https://<instacart_development_domain>/v2/fulfillment/users' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"user_id": "kamalsingh1234",
"first_name": "kamal",
"last_name": "singh",
"phone_number": "8005550101"
}'

A successful JSON response has the status code 200 and the following fields:

{
"user_id": "kamalsingh1234",
"first_name": "Kamal",
"last_name": "Singh",
"phone_number": "8005550101"
}

If the user account already exists, for example if you or someone else has tried this tutorial on your development environment recently, the request returns the status code 400 User already created. You can continue the tutorial with this ID or call the method again with a different user ID.

Production environment tip

Save the generated user ID with your other customer account information and reuse it for all orders by that customer. It is up to you to ensure the user ID remains unique and associated with the correct customer. If the same ID is used for multiple customers, you risk introducing security and privacy concerns.

Fill a cart

To create an order, you need a cart with some items in it. Use your development environment to add an item to the cart that is available at the selected store. Note the UPC number. You'll substitute this value for the variable <item_upc> in requests.

Understand changes required in the checkout process

During the checkout process, your storefront needs to include prompts to collect the information necessary to create an order. For this tutorial, the Create a delivery order request contains sample values for these items.

The information to collect before you create an order includes:

  • A valid delivery address.
  • Confirmation to opt in to receiving SMS notifications during order fulfillment. Default is false.
  • Confirmation to leave the delivery unattended. Default is false.
  • Confirmation if Electronic Benefits Transfer (EBT) is used as a payment method. Default is false.
  • (Optional) Loyalty card number.
  • (Optional) Special instructions.
  • Tip amount.
  • If a cart contains alcohol, the customer's date of birth. The customer must be old enough to legally purchase alcohol in their region. Advise the customer that they must show identification with their date of birth when the order is delivered and that alcohol cannot be left unattended.

Near the end of the checkout process, your storefront needs to handle the following tasks:

  • Display the order details for review, and enable a customer to change items or update any of the collected information.
  • Prompt for payment. Reserve the payment amount but wait to process the payment until after your site receives a callback to confirm that the order was delivered. Refunds might affect the total cost of the order.
  • Prompt the user to select a time slot, as described in the next step.

Reserve a time slot for delivery

Before you can reserve a time slot, you need to retrieve a list of available time slots. The Fulfillment engine assesses the cart items to determine if any items have restrictions that might affect order fulfillment, such as alcohol or weight, and returns suitable time slots. After the customer selects a time slot, you can reserve a time slot for 10 minutes.

Retrieve the list of available time slots. In the request, substitute your values for the variables <instacart_development_domain>, <token>, <item_upc>, and <location_code>.

curl --request POST \
--url 'https://<instacart_development_domain>/v2/fulfillment/users/kamalsingh1234/service_options/cart/delivery' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"address": {
"address_line_1": "50 Beale St",
"postal_code": "94105"
},
"items": [
{
"line_num": "1",
"count": 10,
"weight": 1,
"item": {
"upc": "<item_upc>"
}
}
],
"location_code": "<location_code>
}'

The response contains a list of available time slots. Timestamps are returned in Coordinated Universal Time (UTC).

{
"service_options": [
{
"id": 3310259,
"date": "2021-06-04",
"window": {
"immediate_hour": 2
},
"availability": {
"available": true,
"reasons": [],
"item_codes": []
}
},
{
"id": 10358918,
"date": "2021-06-04",
"window": {
"immediate_hour": 5
},
"availability": {
"available": true,
"reasons": [],
"item_codes": []
}
},
{
"id": 418283417,
"date": "2021-06-04",
"window": {
"start_at": "2021-06-04T23:00:00Z",
"end_at": "2021-06-05T01:00:00Z"
},
"availability": {
"available": true,
"reasons": [],
"item_codes": []
}
},
...
]
}

From your response, choose a time slot to use in this tutorial. You'll substitute the ID for the variable <service_option_id> in the next request.

Reserve the time slot. In the request, substitute your values for the variables <instacart_development_domain>, <token>, and <service_option_id>.

curl --request POST \
--url 'https://<instacart_development_domain>/v2/fulfillment/users/kamalsingh1234/service_options/<service_option_id>/reserve' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json'

The response contains the details about the reserved time slot with the service option hold ID 354282083.

{
"service_option_hold": {
"id": 354282083,
"expires_at": "2021-06-04T18:50:50Z",
"service_option": {
"id": 3310259,
"date": "2021-06-04",
"window": {
"immediate_hour": 2
},
"availability": {
"available": true,
"reasons": [],
"item_codes": []
}
}
}
}

From your response, note the service option hold ID. You'll substitute this value for the variable <service_option_hold_id> when you create the order. The reservation is held for 10 minutes. To book the time slot, create the order.

Production environment tips
  • Convert the UTC timestamps to the customer's time zone before displaying the time slots.
  • To avoid disappointing your customers, make the reservation as close to the end of the checkout process as possible. If a reservation expires before the order is created, Connect still attempts to book the time. Generally speaking, time slots have capacity for more than one order. If, however, the time slot capacity is fully booked, your storefront needs to prompt your customer to select a different time slot.
  • If your retailer site enables customers to change a reserved delivery time slot, send the request again with the new time slot. Connect expires the previous time slot and uses the new one. An order can have only one time slot reserved.

Create a delivery order

Send a request to create an order as soon as possible after reserving the time slot. The order requires a retailer-generated order ID.

Create the order. In the request, substitute your values for the variables <instacart_development_domain>, <token>, <order_id>, <service_option_hold_id>, <location_code>, and <item_upc>.

curl --request POST \
--url 'https://<instacart_development_domain>/v2/fulfillment/users/kamalsingh1234/orders/delivery' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"order_id": "<order_id>",
"service_option_hold_id": "<service_option_hold_id>",
"initial_tip_cents": 1000,
"leave_unattended": true,
"special_instructions": "Ring the doorbell on delivery.",
"location_code": "<location_code>",
"paid_with_ebt": true,
"locale": "en-US",
"user": {
"phone_number": "8005550101",
"sms_opt_in": true
},
"address": {
"address_line_1": "50 Beale St",
"postal_code": "94105"
},
"items": [
{
"line_num": "1",
"count": 10,
"weight": 1,
"replacement_policy": "no_replacements",
"item": {
"upc": "<item_upc>"
}
}
]
}'

The response contains details about the newly created order.

{
"id": "<order_id>",
"status": "brand_new",
"order_url": "https://<instacart_development_domain>/s/Y25Ud2M1RU5m",
"created_at": "2021-06-04T19:04:08Z",
"cancellation_reason": "",
"locale": "en_US",
"fulfillment_details": {
"window_starts_at": "2021-06-04T19:04:07Z",
"window_ends_at": "2021-06-04T21:04:07Z"
},
"items": [
{
"line_num": "1",
"qty": 10.0,
"qty_unit": "each",
"replaced": false,
"replacement_policy": "no_replacements",
"item": {
"upc": "0078735917701",
"rrc": ""
}
}
]
}
Production environment tip

It can take several seconds to receive confirmation that the order is created. For your storefront, consider what you want to show to the customer while they wait for confirmation.

What happens to an order in a production environment?

As previously mentioned, an order created in a development environment is not fulfilled. To complete this tutorial, let's review what happens to orders created in a production environment.

In a production environment, the order is added to a fulfillment batch for the requested store and time slot. Until the batch is assigned to a shopper, you can provide a way for your customers to update an order or cancel an order.

If your retailer site is set up to receive callbacks, your site receives information about events as the order is fulfilled. For example, you are notified when a shopper starts shopping and when the order is delivered. For a list of the available events that you can track, see Event callbacks.

A shopper receives the order and begins shopping. The shopper records items as they are picked from the shelf. If the customer opted in for SMS notifications, the customer receives status messages and can chat with the shopper about replacements and refunds. For more insight into shopper communications, see the Delivery user journey.

tip

You can get all orders for the user account, including the order status, with the Get orders method.

After an order is completed

After an order is delivered to your customer, you can provide a way for your customer to update their tip and give feedback on the order. For more information about updating a tip, see Update a tip. For more information about giving order feedback, see Create or update order feedback (backend) and Create or update order feedback (frontend).

Summary

In this tutorial, we found stores near a customer that offered delivery and created a user account. Then we filled a cart and learned what information needs to be collected during checkout. We reserved a time slot and created an order. We discussed what happens in a production environment while the order is in the fulfillment process. Finally, we discussed providing a way for your customer to update their tip and give feedback on their completed order.