Create a delivery order
POST /v2/fulfillment/users/{user_id}/orders/delivery
Creates a delivery order for the reserved time slot.
If the reservation has expired, Instacart still attempts to book the time slot. If, however, the time slot capacity is filled, your site needs to prompt the customer to select another time slot. The response can take several seconds to return, so for the best customer experience, create the order as soon as possible after the customer completes your checkout process.
If the items in the cart changed after a time slot was reserved, the order creation might fail. For details, see the returned error message.
Order item limitations
If your request specifies an order containing items that exceed any of the following limitations, the order is not created:
- Maximum total quantity of items
- Maximum total weight of beverage items
- Maximum quantity of large or bulky items
For more information about why an order couldn't be created, see the returned error message.
Age verification for alcohol
Some products require age validation in accordance with regional laws, such as alcohol and over-the-counter medication. When a cart contains an age-restricted product, the retailer site must request the customer’s date of birth and include it in the order sent to Instacart. If the birthday is missing or the customer is not old enough to purchase the item, Instacart Connect returns an error or removes the item based on your configuration.
Store location
You can specify the store location in the request. When a shopper shops for an order, they are asked to shop from the selected store location, but there is no guarantee that they shop there.
Phone number requirements
If the user_id parameter in the request path references a user that doesn't have a phone_number, then user.phone_number is required in the body.
Security
| Name | In | Description |
|---|---|---|
Authorization | header | The Authorization header with the bearer token acquired during authentication. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id | path | string | The ID of the user. |
Request
Each items[] in the request requires either a count or a weight. The field that needs to be defined depends on that product's catalog configuration. For more information, see Product quantity types.
| Field | Type | Required | Description |
|---|---|---|---|
order_id | string | The unique retailer-generated order ID to use for the order. The ID can be used later for lookup. | |
service_option_hold_id | integer | The ID of the service option hold. | |
loyalty_number | string | The loyalty number to use for this transaction. | |
initial_tip_cents | integer | The pre-delivery tip amount in cents. | |
leave_unattended | boolean | Indicator if the customer wants the driver to leave the order unattended. Defaults to false. | |
special_instructions | string | Special instructions about the order to pass on to the shopper. | |
location_code | string | The store location code used to look-up cart items. | |
paid_with_ebt | boolean | Indicator if the order contains an EBT payment. Defaults to false. | |
locale | string | The order's locale in IETF Language Tag format. Example: en-US. | |
metadata | Hash | The order-level metadata. | |
applied_express | boolean | Deprecated. Use | |
applied_instacartplus | boolean | Indicates whether the retailer applied Instacart+ membership benefits to the order. Defaults to false. | |
user | OrderUser | Any additional attributes for the user, these take precedence over values set during user create. | |
address | ExpandedAddress | The address being delivered to. | |
items | Array(OrderItem) | The items for the order. |
OrderUser Object
| Field | Type | Required | Description |
|---|---|---|---|
birthday | string | The user's birthday in ISO 8601 format, this is used for alcohol eligibility validation. | |
phone_number | string | The user's phone number. | |
sms_opt_in | boolean | Indicator whether the user has opted-in to receive SMS communications. |
ExpandedAddress Object
| Field | Type | Required | Description |
|---|---|---|---|
address_line_1 | string | The first line of the address, e.g., | |
address_line_2 | string | The second line of the address, e.g., | |
address_type | string | The type of address, e.g., | |
postal_code | string | The postal or zip code of the address. | |
city | string | The city or town of the address, e.g., |
OrderItem Object
| Field | Type | Required | Description |
|---|---|---|---|
line_num | string | The item's line number in the order. | |
count | integer | The count of the item. Must be a non-negative integer. Depending on the item's catalog configuration, either this field or 'weight' is required. | |
weight | number | For items sold by weight, the numerical weight of the item. Depending on the item's catalog configuration, either this field or 'count' is required. The API interprets this value as whatever unit of measure is defined for the item in the catalog, such as lb or kg. Must be a non-negative number. | |
special_instructions | string | Any special instructions about the item selection. | |
replacement_policy | string | One of "no_replacements", "users_choice" (default if replacement_items specified), or "shoppers_choice" (default otherwise). | |
metadata | Hash | The item-level metadata. | |
replacement_items | Array(Replacement_items) | A list of requested replacement items if the original item could not be found. This field needs to be turned on via configuration. Contact your Instacart Connect representative. | |
item | Item | The item's code. |
Replacement_items Object
One of the following:
| Field | Type | Required | Description |
|---|---|---|---|
upc | string | The item's universal product code (upc). |
or
| Field | Type | Required | Description |
|---|---|---|---|
rrc | string | The item's retailer reference code (rrc). |
Item Object
One of the following:
| Field | Type | Required | Description |
|---|---|---|---|
upc | string | The item's universal product code (upc). |
or
| Field | Type | Required | Description |
|---|---|---|---|
rrc | string | The item's retailer reference code (rrc). |
Request examples
- cURL
- Java
- Python
- Go
curl --request POST \
--url 'https://connect.instacart.com/v2/fulfillment/users/{user_id}/orders/delivery' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"order_id": "string",
"service_option_hold_id": 1,
"loyalty_number": "string",
"initial_tip_cents": 1,
"leave_unattended": true,
"special_instructions": "string",
"location_code": "string",
"paid_with_ebt": true,
"locale": "string",
"metadata": {
"key1": "value1",
"key2": "value2"
},
"applied_express": true,
"applied_instacartplus": true,
"user": {
"birthday": "string",
"phone_number": "string",
"sms_opt_in": true
},
"address": {
"address_line_1": "string",
"address_line_2": "string",
"address_type": "string",
"postal_code": "string",
"city": "string"
},
"items": [
{
"line_num": "string",
"count": 1,
"weight": 1,
"special_instructions": "string",
"replacement_policy": "no_replacements",
"metadata": {
"key1": "value1",
"key2": "value2"
},
"replacement_items": [
{
"upc": "string"
}
],
"item": {
"upc": "string"
}
}
]
}'
HttpResponse<String> response = Unirest.post("https://connect.instacart.com/v2/fulfillment/users/{user_id}/orders/delivery")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer <token>")
.body("{\n \"order_id\": \"string\",\n \"service_option_hold_id\": 1,\n \"loyalty_number\": \"string\",\n \"initial_tip_cents\": 1,\n \"leave_unattended\": true,\n \"special_instructions\": \"string\",\n \"location_code\": \"string\",\n \"paid_with_ebt\": true,\n \"locale\": \"string\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"applied_express\": true,\n \"applied_instacartplus\": true,\n \"user\": {\n \"birthday\": \"string\",\n \"phone_number\": \"string\",\n \"sms_opt_in\": true\n },\n \"address\": {\n \"address_line_1\": \"string\",\n \"address_line_2\": \"string\",\n \"address_type\": \"string\",\n \"postal_code\": \"string\",\n \"city\": \"string\"\n },\n \"items\": [\n {\n \"line_num\": \"string\",\n \"count\": 1,\n \"weight\": 1,\n \"special_instructions\": \"string\",\n \"replacement_policy\": \"no_replacements\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"replacement_items\": [\n {\n \"upc\": \"string\"\n }\n ],\n \"item\": {\n \"upc\": \"string\"\n }\n }\n ]\n}")
.asString();
import http.client
conn = http.client.HTTPSConnection("connect.instacart.com")
payload = "{\n \"order_id\": \"string\",\n \"service_option_hold_id\": 1,\n \"loyalty_number\": \"string\",\n \"initial_tip_cents\": 1,\n \"leave_unattended\": true,\n \"special_instructions\": \"string\",\n \"location_code\": \"string\",\n \"paid_with_ebt\": true,\n \"locale\": \"string\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"applied_express\": true,\n \"applied_instacartplus\": true,\n \"user\": {\n \"birthday\": \"string\",\n \"phone_number\": \"string\",\n \"sms_opt_in\": true\n },\n \"address\": {\n \"address_line_1\": \"string\",\n \"address_line_2\": \"string\",\n \"address_type\": \"string\",\n \"postal_code\": \"string\",\n \"city\": \"string\"\n },\n \"items\": [\n {\n \"line_num\": \"string\",\n \"count\": 1,\n \"weight\": 1,\n \"special_instructions\": \"string\",\n \"replacement_policy\": \"no_replacements\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"replacement_items\": [\n {\n \"upc\": \"string\"\n }\n ],\n \"item\": {\n \"upc\": \"string\"\n }\n }\n ]\n}"
headers = {
'Accept': "application/json",
'Content-Type': "application/json",
'Authorization': "Bearer <token>"
}
conn.request("POST", "/v2/fulfillment/users/{user_id}/orders/delivery", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://connect.instacart.com/v2/fulfillment/users/{user_id}/orders/delivery"
payload := strings.NewReader("{\n \"order_id\": \"string\",\n \"service_option_hold_id\": 1,\n \"loyalty_number\": \"string\",\n \"initial_tip_cents\": 1,\n \"leave_unattended\": true,\n \"special_instructions\": \"string\",\n \"location_code\": \"string\",\n \"paid_with_ebt\": true,\n \"locale\": \"string\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"applied_express\": true,\n \"applied_instacartplus\": true,\n \"user\": {\n \"birthday\": \"string\",\n \"phone_number\": \"string\",\n \"sms_opt_in\": true\n },\n \"address\": {\n \"address_line_1\": \"string\",\n \"address_line_2\": \"string\",\n \"address_type\": \"string\",\n \"postal_code\": \"string\",\n \"city\": \"string\"\n },\n \"items\": [\n {\n \"line_num\": \"string\",\n \"count\": 1,\n \"weight\": 1,\n \"special_instructions\": \"string\",\n \"replacement_policy\": \"no_replacements\",\n \"metadata\": {\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n },\n \"replacement_items\": [\n {\n \"upc\": \"string\"\n }\n ],\n \"item\": {\n \"upc\": \"string\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
Response
| Field | Type | Required | Description |
|---|---|---|---|
id | string | The retailer-generated order ID. | |
status | string | The current status of the order. | |
order_url | string | The URL of the Instacart-hosted order status page. If the retailer has opted not to use this feature, this field will be | |
created_at | string | The time of order creation in ISO 8601 format. | |
cancellation_reason | string | The reason the order was canceled. Only present in canceled orders. One of the following:
| |
locale | string | Indicates how the order is localized. | |
is_express | boolean | Deprecated. Use | |
is_instacartplus | boolean | Indicates whether the order received Instacart+ membership benefits. Defaults to false. | |
metadata | Hash | The order-level metadata. | |
fulfillment_details | OrderFulfillmentDetails | The order's fulfillment details. | |
warnings | Array(Error) | Any warnings associated with this request. | |
items | Array(OrderItem) | The items in the order. |
OrderFulfillmentDetails Object
| Field | Type | Required | Description |
|---|---|---|---|
store_location | string | The location code of the store where the order was fulfilled. This field's value is often the same as the | |
window_starts_at | string | The start of the fulfillment window in ISO 8601 format. | |
window_ends_at | string | The end of the fulfillment window in ISO 8601 format. | |
delivered_at | string | The time the order was delivered to the customer in ISO 8601 format. Only present for completed deliveries. | |
bag_count | integer | The number of bags in the order, as reported by the shopper. | |
handoff_window_starts_at | string | The start of the store-associate-to-Instacart-shopper handoff window in ISO 8601 format. This field is only populated for last mile delivery (i.e., delivery only) orders. | |
handoff_window_ends_at | string | The end of the store-associate-to-Instacart-shopper handoff window in ISO 8601 format. This field is only populated for last mile delivery (i.e., delivery only) orders. |
Error Object
| Field | Type | Required | Description |
|---|---|---|---|
error | ErrorDetails | The error details. | |
meta | MetaError | Metadata about the error, including the items associated with it. |
ErrorDetails Object
| Field | Type | Required | Description |
|---|---|---|---|
message | string | A human-readable description of the error. | |
error_code | integer | A numeric code that identifies the error type. |
MetaError Object
| Field | Type | Required | Description |
|---|---|---|---|
items | Array(ItemInfo) | The items that triggered the error. |
ItemInfo Object
| Field | Type | Required | Description |
|---|---|---|---|
item_code | string | The retailer reference code (RRC) or universal product code (UPC) of an item that triggered the error. |
OrderItem Object
| Field | Type | Required | Description |
|---|---|---|---|
line_num | string | The item's line number as provided by the retailer in the create order request. | |
qty | number | The quantity of the item. For unpicked items, this is the ordered quantity. For picked items, this is the delivered quantity. | |
qty_unit | string | The unit of measure for the quantity. Either | |
qty_fulfilled | number | The fulfilled quantity of the item (the actual quantity picked and delivered). | |
qty_fulfilled_unit | string | The unit of measure for the fulfilled quantity. Either | |
qty_requested | number | The initially requested quantity of the item (what the customer originally ordered). | |
qty_requested_unit | string | The unit of measure for the initially requested quantity. Either | |
replaced | boolean | Indicates whether the item was replaced. This is | |
scan_code | string | The barcode or scan code that the shopper scanned when picking this item. | |
replacement_policy | string | The replacement policy for the item. One of the following:
| |
shopper_provided_item_name | string | The item name provided by shoppers for items that they added. | |
metadata | Hash | The item-level metadata. | |
shopper_provided_item_price | Money | The item price provided by shoppers for items that they added. | |
item | Item | The item's codes. |
Money Object
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | The amount of a specified currency. | |
currency | string | The currency type in ISO 4217 format. For example: USD. |
Item Object
| Field | Type | Required | Description |
|---|---|---|---|
upc | string | The item's universal product code (UPC). For unpicked items, this is the requested UPC. For picked items, this is the delivered UPC. | |
rrc | string | The item's retailer reference code (RRC). For unpicked items, this is the requested RRC. For picked items, this is the delivered RRC. | |
requested_upc | string | The UPC of the item that the customer originally requested to purchase. | |
requested_rrc | string | The RRC of the item that the customer originally requested to purchase. | |
delivered_upc | string | The UPC of the item that was actually picked and delivered to the customer. If the item was replaced, this will differ from the | |
delivered_rrc | string | The RRC of the item that was actually picked and delivered to the customer. If the item was replaced, this will differ from the |
Response examples
200 Success
200Order created with item upc200Order created with warnings200Order created with item rrc
{
"id": "12345676789012345678780",
"status": "created",
"order_url": "https://example.com/example-order",
"created_at": "2018-02-22T00:00:00Z",
"cancellation_reason": "shopper_driven",
"locale": "en_US",
"is_express": true,
"is_instacartplus": true,
"fulfillment_details": {
"store_location": "000-31921",
"window_starts_at": "2018-02-22T00:00:00Z",
"window_ends_at": "2018-02-22T00:30:00Z"
},
"items": [
{
"line_num": "14",
"qty": 5,
"qty_unit": "each",
"replaced": false,
"scan_code": "00070481001125",
"replacement_policy": "shoppers_choice",
"rx": false,
"item": {
"upc": "123456789026",
"rrc": "",
"requested_upc": "123456789026",
"requested_rrc": "",
"delivered_upc": "123456789026",
"delivered_rrc": ""
}
}
]
}
{
"id": "12345676789012345678780",
"status": "created",
"order_url": "https://example.com/example-order",
"created_at": "2018-02-22T00:00:00Z",
"cancellation_reason": "shopper_driven",
"locale": "en_US",
"is_express": true,
"is_instacartplus": true,
"fulfillment_details": {
"store_location": "000-31991",
"window_starts_at": "2018-02-22T00:00:00Z",
"window_ends_at": "2018-02-22T00:30:00Z"
},
"warnings": [
{
"error": {
"message": "1 item not found",
"error_code": 1001
},
"meta": {
"items": [
{
"item_code": "000000004011"
}
]
}
}
],
"items": [
{
"line_num": "21",
"qty": 6,
"qty_unit": "each",
"replaced": false,
"scan_code": "00070481001132",
"replacement_policy": "shoppers_choice",
"rx": false,
"item": {
"upc": "123456789033",
"rrc": "",
"requested_upc": "123456789033",
"requested_rrc": "",
"delivered_upc": "123456789033",
"delivered_rrc": ""
}
}
]
}
{
"id": "12345676789012345678780",
"status": "created",
"order_url": "https://example.com/example-order",
"created_at": "2018-02-22T00:00:00Z",
"cancellation_reason": "shopper_driven",
"locale": "en_US",
"is_express": true,
"is_instacartplus": true,
"fulfillment_details": {
"store_location": "000-32014",
"window_starts_at": "2018-02-22T00:00:00Z",
"window_ends_at": "2018-02-22T00:30:00Z"
},
"items": [
{
"line_num": "23",
"qty": 10,
"qty_unit": "each",
"replaced": false,
"scan_code": "00070481001134",
"replacement_policy": "shoppers_choice",
"rx": false,
"item": {
"upc": "123456789035",
"rrc": "011-849503940",
"requested_upc": "123456789035",
"requested_rrc": "011-849503940",
"delivered_upc": "123456789035",
"delivered_rrc": "011-849503940"
}
}
]
}
4XX Errors
Error responses return either a single error or multiple errors.
| HTTP Code | Cause | Error Message | Error Code | Error Meta |
|---|---|---|---|---|
400 | Invalid user id | "User Not Found" | 1001 | {"key":"user_id"} |
400 | User with invalid phone number | "Required parameter missing or invalid" | 1001 | {"key":"user_phone"} |
400 | Invalid Quantity, expected count | "One of these items had an invalid quantity amount, 0001234567892 expected count" | 2012 | {"item_code":"0001234567892","expected_param":"count","error_name":"WrongQuantityParameterError"} |
400 | Expired ETA option hold | "ETA option hold has expired." | 1001 | {"key":"service_option_hold_id"} |
400 | Invalid replacement_policy | "is not included in the list" | 1001 | {"key":"items[0].replacement_policy"} |
400 | Invalid quantity (negative count) | "must be greater than or equal to 0" | 1001 | {"key":"items[0].count"} |
400 | Invalid quantity (negative weight) | "must be greater than or equal to 0" | 1001 | {"key":"items[0].weight"} |
400 | Invalid postal code | "not found" | 1001 | {"key":"postal_code"} |
400 | Unsupported postal code | "not supported" | 1001 | {"key":"postal_code"} |
400 | Invalid service option hold | "Hold not found" | 1001 | {"key":"service_option_hold_id"} |
400 | User and order without phone number | "can't be blank" | 1001 | {"key":"user.phone_number"} |
400 | Tip over maximum | "Tip value is above maximum: $300.00." | 1001 | {"key":"initial_tip_cents"} |
400 | Invalid location code | "Could not find specified store." | 1001 | {"key":"location_code"} |
400 | Invalid order params* | "There were issues with your request" | 9999 | Not applicable |
400 | Age requirement otc medicine | "You must be over 18 to purchase over the counter medicine in your cart." | 1001 | {"items":[{"item_upc":"12345"}]} |
400 | Fails alcohol compliance check | "Alcoholic items can not be added to this order. Please remove and retry." | 2001 | Not applicable |
400 | Invalid items | "2 items not found." | 2000 | {"upcs":["111111111111","222222222222"],"items":[{"item_upc":"111111111111"},{"item_upc":"222222222222"}]} |
400 | Insufficient items to meet order pass threshold | "1 item not found. Insufficient items to meet order pass threshold." | 2008 | {"upcs":["123"],"items":[{"item_upc":"123"}],"error_name":"InsufficientItemsError","item_found_ratio":0.5,"min_item_found_ratio":0.8,"total_cost_cents":1000,"min_total_cost_cents":2000} |
400 | Invalid address | "invalid_address" | 1001 | {"key":"address"} |
400 | Invalid zip code for alcohol | "Cannot deliver alcohol to this zip code." | 1001 | {"items":[{"item_upc":"928473737373"}],"key":"zip_code"} |
400 | Order id already exists | "Order already in use." | 1003 | Not applicable |
400 | Request could not be processed at this time | "The request could not be completed at this time, try again later." | 2003 | {"wait":"30"} |
400 | Duplicate items were provided | "Duplicate items provided for this order." | 2007 | {"duplicate_items":[{"item_upc":"123456789999","item_rrc":null,"line_num":"0"},{"item_upc":"123456789999","item_rrc":null,"line_num":"1"}]} |
400 | Duplicate line nums | "Duplicate line_num values not allowed: 1" | 2006 | {"duplicate_line_nums":["1"]} |
400 | Alcohol outside of allowed time window | "State law restricts selling alcohol during the window you selected. Please change your delivery window to add alcohol." | 2001 | {"upcs":["alcohol_upc"],"items":[{"item_upc":"alcohol_upc"}]} |
400 | Deactivated user account | "The user account was deactivated." | 1002 | {"key":"access_token"} |
400 | Service option is no longer available | "The delivery time you selected is no longer available - please select another time" | 1001 | {"key":"service_option_id"} |
400 | Too many big and bulky items | "The number of big and bulky items in your cart exceeds our maximum limit for a single delivery. Please remove 2 such items from your cart to continue." | 2023 | Not applicable |
400 | Too much beverage | "The weight of beverages in your cart exceeds our maximum limit for a single delivery. Please remove 20lb of beverages from your cart to continue." | 2026 | Not applicable |
400 | Too many items | "The number of items in your cart exceeds our maximum limit for a single delivery. Please remove 15 items from your cart to continue." | 2024 | Not applicable |
400 | Too much weight | "The total weight of items in your cart exceeds our maximum limit for a single delivery. Please remove 20 lb from your cart to continue." | 2027 | Not applicable |
400 | Some items are not deliverable | "Some items are not deliverable" | 2005 | {"items":[{"item_upc":"123456789083"}]} |
400 | Invalid Quantity, expected weight | "One of these items had an invalid quantity amount, some_upc expected weight" | 2012 | {"upc":"some_upc","item_code":"some_upc","expected_param":"weight"} |
400 | User birthday missing or invalid for alcohol order | "Required parameter missing or invalid" | 1001 | {"key":"user_birthday","items":[{"item_upc":"alcohol_upc"}]} |
400 | Another order created recently | "Another order has been recently created for this user, please try again in a little while." | 2003 | {"wait":10,"retry":true} |
403 | Inactive user | "User Not Active" | null | Not applicable |
404 | Order not found | "Resource not found" | 4000 | Not applicable |