The Delivery API is designed to allow technology partners seamlessly integrate third-party delivery providers into their solution.
Problem
Tech services that work with restaurants, such as POS systems or online ordering solutions, often face challenges when providing delivery options. Without a standardized delivery integration, they have to either leave delivery logistics entirely up to the restaurants or integrate separately with various delivery providers, which is time-consuming and complex. Managing different APIs, workflows, and tracking systems for each delivery provider creates operational inefficiencies and makes scaling difficult. This lack of integration can result in poor customer experience, delayed deliveries, and limited delivery tracking visibility for restaurants and their customers.
Delivery API Solution
We offer a unified, easy-to-integrate API that connects tech platforms to multiple third-party delivery providers, such as DoorDash Drive, DeliverLogic, and others in the future. This allows you to offer seamless delivery management for your customers, without having to build complex integrations with each delivery provider individually.
This API abstracts the complexity of managing deliveries across multiple platforms and offers a plug-and-play solution for tech services.
List of Supported Delivery Providers and Their Capabilities
DoorDash Drive | DeliverLogic | |
---|---|---|
delivery_provider_id | doordash_drive | delivery_logic |
Create quote | ✅ Up to 5 min before delivery | ❌ |
Accept quote | ✅ | ❌ |
Cancel method | ✅ Before courier assign | ✅ Anytime |
Prerequisite to Use the Delivery API
Create an Authorization Token
If you don't have access to the KitchenHub API, you must first obtain API keys. Using these keys, you can generate an authorization token to authenticate your requests. This token ensures secure communication between your system and the API by validating each request.
For more information, refer to the Auth API.
Connect a Restaurant
Before managing deliveries, you must first set up your restaurant's locations and stores. This setup allows the API to manage deliveries for the registered stores.
For detailed instructions, refer to the KitchenHub API Locations documentation.
Please note
You need to save store ID on your side to order for further delivery requests for this store.
The following properties will be used in the delivery object from the store and location settings:
- Store Name: The name of the store.
- Street: Restaurant's street address.
- City: Restaurant's city.
- State: Restaurant's state.
- Zipcode: Restaurant's postal code.
- location_timezone: The timezone of the location (e.g., America/New_York).
- pickup_notes: Notes about the location's pickup instructions.
Connect Delivery Providers to the Store
In addition to setting up location and store, you must connect them with a delivery provider. For detailed instructions on how to connect a store to a delivery provider, visit the Providers API documentation.
Setup Webhook for Delivery Notifications (Optional)
To receive real-time updates on your deliveries, you can configure webhooks of type Delivery. These webhooks will notify you instantly of key events in the delivery process, including:
- QuoteCreated: Notification when a delivery quote is generated.
- DeliveryCreated: Notification when a delivery order has been successfully created.
- DeliveryUpdated: Notification when the status of a delivery changes.
Setting up webhooks ensures timely updates and enhances tracking capabilities for your deliveries. For a step-by-step guide on configuring webhooks and details on the different event types, refer to the webhook section in the documentation.
How It Works
The image below presents a high-level overview of how our Delivery API works.
- Customer places order → Sent via Delivery API to KitchenHub.
- Delivery API routes the order to the Delivery Connector.
- Delivery Manager sends the order to a delivery Provider (e.g., Doordash drive).
- Provider assigns a driver and notifies Delivery Manager when the driver arrives.
- Delivery Manager updates the Customer Webhook with the new status (e.g. "Placed").
- Provider sends further updates ("Enroute", "Delivered") back to the Delivery Manager.
- Customer Webhook receives final updates, informing the customer.
Step by step guide how to use deliveries
Please note
Before sending delivery requests, please ensure that all prerequisites (such as setting up stores, locations, and connecting to providers) are correctly configured to avoid issues.
Create Delivery for Providers That do not Support Quotes
Step 1: Create a Delivery
Use the Create delivery
method. This method allowed only for providers that do not support quotes. Response for create delivery method will return an immediate confirmed delivery. The is_quote
flag indicates whether the response includes confirmed delivery.
The pickup_info is automatically retrieved from the store settings, which include details such as store_address, store_name, and store_notes. If you need to update location use PATCH 'Update location'.
Regular Delivery (ASAP)
For a regular, ASAP delivery, the scheduled_order
should be set to false
, and the request should include a pickup_info field
with the time the driver should arrive for the pickup.
Here is an example of request:
{
"order_id": "2221728910434151", // Unique identifier for the order in your system
"scheduled_order": false,
"store_id": "9ee8e2fc-9459-4e4d-aad9-d91869a5a626", // Unique identifier for the store in KitchenHub
"pickup_info": {
"pickup_datetime": "2024-09-18T22:25:19.552Z" // UTC date-time when the driver should pick up the order (ISO 8601 format)
},
"customer_info": {
"first_name": "Crocodile", // Customer's first name
"last_name": "Gene", // Customer's last name
"phone_number": "+12345677877" // Customer's phone number, including the country code
},
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US",
"drop_off_notes": "Drop-off Notes"
},
"charges": {
"total": 55.0, // Total amount for the order, in local currency
"delivery_tips": 10.0, // Tip amount for the driver, in local currency
"subtotal": 45.0 // Subtotal amount for the order, in local currency
}
}
{
"id": 6215559200112640, // Unique quote id
"status": "new",
"delivery_order_id": "fc5960f3f1594126979b9dce7c0c379d",
"delivery_fee": "9.75", // Calculated delivery fee by a provider, in local currency. This field is optional for providers that do not support quotes.
"is_quote": false
}
Scheduled Delivery
For scheduled deliveries, set scheduled_order
to true
, leave pickup_info
as null
, and specify the delivery time in the drop_off_info.drop_off_datetime
field.
Scheduled delivery example request:
{
"scheduled_order": true, // Boolean indicating this is a scheduled delivery
"pickup_info": null, // For scheduled deliveries, pickup information is not needed
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US", // Full address where the order should be delivered
"drop_off_datetime": "2024-09-25T16:30:00Z", // Scheduled UTC date-time for the delivery
"drop_off_notes": "Drop-off Notes" // Additional instructions for the driver about the delivery
}
…
}
Step 2: Check How Delivery Status Changing
There are two main ways to monitor the status of a delivery:
Receive Notifications via Webhook:
You can set up a webhook to receive real-time updates on delivery status changes. This way, every time the status of a delivery is updated (e.g., from 'placed' to 'enroute' or 'delivered'), your system will automatically be notified. This method ensures you're always up to date without needing to constantly check the status manually.
Poll the Delivery Status Using GET Methods:
If you prefer a manual approach or need a backup option, you can poll the delivery status by using the Get delivery by Id
method. This will return the current status of a specific delivery based on its unique ID. Alternatively you can use the GET all deliveries
method, providing the order_id
as a query parameter to retrieve the related deliveries. This method allows you to continuously check the status at intervals that suit your process.
Possible delivery statuses
- New: The delivery order has been created, but has not yet been processed. This is the initial state of a delivery order when it is first generated in the system. At this stage, no action has been taken yet, and the order is waiting to be placed or assigned to a delivery driver.
- Placed: The delivery order has been confirmed and is now scheduled for delivery. At this stage, the order is acknowledged by the system, and the process of assigning a driver or preparing the delivery has begun. The order is now in the pipeline for further processing.
- Arrived: The delivery driver has arrived at the merchant location. This status indicates that the delivery is in the final stage, with the driver present at the store address, ready to take the order and go to the customer.
- Enroute: The delivery is currently on its way to the customer. This status indicates that the delivery is actively being transported to the specified destination.
- Delivered: The delivery has been successfully completed. The order has been handed over to the customer, and the delivery process is now closed. This status indicates a successful and finalized delivery transaction.
- Cancelled: The delivery order has been cancelled, either by the customer or by delivery service. This status indicates that the delivery will not proceed, and no further action is required.
Step 3: Retrieve All Deliveries. Check Delivery History (optional)
To view a complete history of all deliveries, including both active and completed ones, use the GET 'Get all deliveries'
method. This allows you to retrieve detailed information about past and ongoing deliveries. You can also filter the results by various parameters to focus on specific deliveries.
Query Parameters:
Parameters | Description | Example |
---|---|---|
store_id | The KitchenHub ID of the store. This parameter allows you to filter deliveries by the store registered in the KitchenHub system. | 5d84d149-342f-4202-a614-05ae080a2d7a |
partner_store_id | The ID of the partner store. This can be any identifier used by the external partner system to identify the store. Use this parameter to filter deliveries for a particular partner store. | partner_store_001 |
date_from | The start date and time for filtering deliveries. The format should follow yyyy-MM-dd'T'HH:mm:ss'Z' in UTC time. | 2024-09-23T16:12:33Z |
date_to | The end date and time for filtering deliveries. Use the same format yyyy-MM-dd'T'HH:mm:ss'Z' in UTC | 2024-09-30T16:12:33Z |
status | Filters deliveries based on their status. You can specify one or more statuses to retrieve deliveries that match your criteria. | delivered |
order_id | Filter by a specific order ID. A non-unique identifier assigned to a delivery order. Use this parameter to filter deliveries based on the provided order ID, though keep in mind that multiple deliveries may share the same order_id. | 865d29f4-ae83-4b97-9cf8-de74f3e46f06 |
Create Delivery for providers That Support Quotes
Step 1: Create a Quote
Use the Create delivery quote
method as in the previous step.
{
"scheduled_order": true, // Boolean indicating this is a scheduled delivery quote
"pickup_info": null, // For scheduled deliveries quotes, pickup information is not needed
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US", // Full address where the order should be delivered
"drop_off_datetime": "2024-09-25T16:30:00Z", // Scheduled UTC date-time for the delivery quote
"drop_off_notes": "Drop-off Notes" // Additional instructions for the driver about the delivery
}
…
}
Step 2: Accept Quote Delivery
For providers that offer quotes, you must approve the quote by using the POST 'Accept quote delivery'
method before proceeding with the delivery.
{
"tip": 9.75, // Optional field. Tips for delivery driver
"store_id": "9ee8e2fc-9459-4e4d-aad9-d91869a5a626"
}
{
"id": 467338,
"order_id": "2221728910434151",
"store_id": "9ee8e2fc-9459-4e4d-aad9-d91869a5a626",
"scheduled_order": false,
"delivery_order_id": "183a2ff75b944a5d83b32125f0f54bb6",
"cancellation_reason": null,
"delivery_type": "restaurant",
"pickup_info": {
"pickup_datetime": "2024-09-18T22:25:19.552000Z",
"store_name": "Auto Delivery Enabled DoorDash Drive",
"store_address": "19 North Park Avenue, Rockville Centre, NY 11570",
"pickup_notes": null,
"estimated_pickup_at": null
},
"customer_info": {
"first_name": "first_name test",
"last_name": "last_name test",
"phone_number": "+12345677877",
"email": null
},
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US",
"drop_off_datetime": null,
"drop_off_notes": "Drop-off Notes",
"estimated_dropoff_at": null
},
"charges": {
"total": "55.0",
"delivery_fee": "9.75",
"delivery_tips": "10",
"subtotal": 133.0
},
"status": "new",
"created_at": "2024-10-09T07:44:21.885334Z",
"delivery_provider_id": "doordash_drive",
"courier_info": null,
"delivery_at": null,
"canceled_at": null,
"accepted_at": null,
"is_mock_delivery": false
}
Quotes FAQ
When is a Quote Generated?
Before creating a delivery, you can request a quote. During this process, you provide the pickup and dropoff addresses, and providers that support quotes will verify whether these addresses are within their service area. They will then calculate the delivery fee and provide an estimated time for pickup and dropoff. You'll receive a response containing the delivery fee and other quote details. If the fee and time estimates are acceptable, you need to accept the quote. Note that a quote must be accepted within 5 minutes of being requested. After 5 minutes, the quote expires, and you'll need to request a new one. If you do not call the POST Accept Quote Delivery
method, the delivery will not be created. When calling Get Delivery by ID
, no delivery will be shown until the Accept Delivery
method is invoked.
Can You Request a New Quote?
New quotes can be requested after a waiting period of 5 minutes, specifically for providers that support this feature. For those that do not, the delivery will be created immediately without generating a quote.
What Happens If You Don't Accept a Quote?
In the event that you do not accept a quote, it will automatically expire after 5 minutes. Once it expires, you will need to initiate a new request for a quote.
What Happens If Call This Method on a Provider That Doesn't Support Quote?
If you attempt to call the Accept delivery
method for a provider that does not support quotes, the system will return an error with a status code of 405 and the message: "Abort processing. Provider is not implemented accept method."
However, this does not interrupt the delivery process, and the delivery will proceed as expected without requiring quote acceptance.
Testing Integration
To test the Delivery API for KitchenHub, there are two options: through the dashboard or the API. Below is the documentation for both approaches, including how to create, update, and manage deliveries in test mode.
Test Delivery via Dashboard
- Create Delivery in Dashboard:
- Open the KitchenHub dashboard.
- Go to any test location and open Delivery section.
- Create a new delivery, and fill out the delivery details.
- Enable the Test Delivery toggle. This ensures your delivery actions are simulated without interacting with real delivery providers.
- Submit the form.
- Change Status in Dashboard:
- In test mode, you can directly update the delivery status (e.g., "Enroute," "Delivered") within the dashboard interface.
- Without the Test Delivery toggle enabled, the system will send the delivery request to actual providers like DoorDash or UberEats.
Test Delivery via API
This method allows for more control over delivery creation, updates, and cancellation through the API.
Step 1: Create a Mock Delivery
To create a test delivery, use the POST /v2/mock/delivery/
endpoint.
- Request Payload: The payload mirrors a real delivery but includes an additional field,
delivery_provider_id
, which specifies the provider (e.g., "doordash_drive"). - No Provider Integration Required: For mock deliveries, you don’t need to connect to actual delivery providers.
{
"order_id": "865d29f4-ae83-4b97-9cf8-de74f3e46f06",
"scheduled_order": false,
"store_id": "5d84d149-342f-4202-a614-05ae080a2d7a",
"delivery_provider_id": "doordash_drive",
"pickup_datetime": {
"pickup_datetime": "2024-09-18T22:25:19.552Z"
},
"customer_info": {
"first_name": "Test",
"last_name": "Customer",
"phone_number": "+12345677877"
},
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US",
"drop_off_notes": "Leave at the door"
},
"charges": {
"total": 55.0,
"delivery_tips": 10.0,
"subtotal": 45.0
}
}
- Response: The
is_mock_delivery
flag will be set totrue
, indicating that this delivery is simulated.
Step 2: Accept Quote (Optional)
If the provider returns a quote, use POST /v2/mock/delivery/accept
to confirm the delivery. Not all providers will require this step.
Step 3: Cancel Delivery (Optional)
To cancel a mock or real delivery, use the PUT /v2/mock/delivery/{delivery_id}/cancel
.
Step 4: Simulate of Updating Delivery Status
For mock deliveries, you can manually update the delivery status by using the PUT /v2/mock/delivery/{delivery_id}/status
.
Possible Status Values:
- "Placed": The delivery is scheduled.
- "Arrived": The driver is at the pickup location.
- "Enroute": The order is on its way to the customer.
- "Delivered": The order has been delivered.
This allows for testing of different delivery phases without involving real drivers or customers.
Mock delivery response example:
{
"id": 2345678996234567,
"order_id": "865d29f4-ae83-4b97-9cf8-de74f3e46f06",
"scheduled_order": false,
"store_id": "5d84d149-342f-4202-a614-05ae080a2d7a",
"is_mock_delivery": true
}
By following these steps, you can create and test deliveries either through the KitchenHub dashboard or directly through the API without affecting real-world delivery operations.
Delivery Model
The Delivery object is detailed below, with a sample instance included for clarity. This object will contain an “ID” field that is crucial for tracking and updating the delivery status. All newly created delivery orders will start with a status of "New."
Property | Type | Nullable | Description |
---|---|---|---|
id | integer | No | A unique identifier for the delivery |
order_id | string | No | A identifier for the order, you can use your order ID |
store_id | string | No | A unique identifier for the store where the order is being processed |
scheduled_order | boolean | Yes | Indicates whether the order is scheduled for a future time or is immediate. |
delivery_order_id | string | Yes | A unique identifier from the delivery order. |
cancellation_reason | string | Yes | The reason for cancellation if the delivery is canceled. |
delivery_type | DeliveryType[str] | No | The type of delivery.restaurant : self-delivery using delivery services such as DoorDash Drive or Delivery Logic.provider : delivery by provider itself(GrubHub, UberEats, etc.). |
pickup_info | Dict[str, PickupInfo] | No | Pulled from the location settings. |
customer_info | Dict[str, CustomerInfoSerializer] | No | Detailed information about the customer placing the order. |
drop_off_info | Dict[str, DropOffInfo] | No | Detailed information about the drop-off location and time. |
charges | Dict[str, ChargesSerializer] | No | Detailed breakdown of charges for the delivery service |
status | DeliveryStatus[str] | No | The current status of the delivery.placed : The delivery has been confirmed and scheduled. It is now in the queue for further processing.arrived : The driver has reached the merchant’s location, ready to collect the order.Enroute : The order is on its way to the customer.delivered : The delivery has been successfully completed and handed to the customer.cancelled : The delivery has been canceled and will not proceed. |
created_at | date-time | No | The timestamp when the delivery object was created, in UTC. |
delivery_provider_id | string | No | The service handling the delivery. |
courier_info | Dict[str, CourierInfoSerializer] | Yes | Detailed information about the courier assigned to the delivery. |
delivered_at | date-time | Yes | May be null until delivery has occurred, in UTC. |
cancelled_at | date-time | Yes | May be null if a delivery has not been cancelled, in UTC. |
accepted_at | date-time | Yes | May be null until delivery has been accepted, in UTC. |
is_mock_delivery | boolean | No | flag indicating real or fake delivery created |
PickupInfo Object
Property | Type | Nullable | Description |
---|---|---|---|
store_name | string | No | Populated from a store name. |
store_address | string | No | Populated from a store address. |
pickup_notes | string | Yes | Populated from a store. |
estimated_pickup_at | date-time | Yes | The estimated time when the order will be ready for pickup. |
CustomerInfoSerializer Object
Property | Type | Nullable | Description |
---|---|---|---|
first_name | string | No | The customer's first name. |
last_name | string | No | The customer's last name. |
phone_number | string | No | The customer's contact phone number. Must adhere to E.164 international phone number standard. |
string | Yes | The customer's email address. |
DropOffInfo Object
Property | Type | Nullable | Description |
---|---|---|---|
drop_off_address | string | No | The address where the order will be delivered. |
drop_off_datetime | date-time | Yes | The scheduled date and time for the drop-off at the delivery location. Only for scheduled delivery. |
drop_off_notes | string | Yes | Any special instructions or notes related to the drop-off. |
estimated_dropoff_at | date-time | Yes | The estimated time when the order will be delivered. |
ChargesSerializer Object
Property | Type | Nullable | Description |
---|---|---|---|
total | decimal | No | The total amount to be paid. |
delivery_fee | decimal | Yes | The fee charged for the delivery service. |
delivery_tips | decimal | Yes | The tips given to the delivery person. |
subtotal | decimal | Yes | The subtotal amount. |
CourierInfoSerializer
Property | Type | Nullable | Description |
---|---|---|---|
id | string/int | Yes | The unique identifier for the courier assigned to this delivery. |
name | string | Yes | The name of the courier. |
phone_number | string | Yes | The contact phone number of the courier. |
phone_code | string | Yes | The international dialing code for the courier's phone number. |
photo_url | string | Yes | A URL to the courier's photo. |
vehicle_type | string | Yes | The type of vehicle used by the courier for the delivery. |
Delivery Object Example
{
"id": 467338,
"order_id": "222172845",
"store_id": "5d84d149-342f-4202-a614-05ae080a2d7a",
"scheduled_order": false,
"delivery_order_id": "183a2ff75b944a5d83b32125f0f54bb6",
"cancellation_reason": null,
"delivery_type": "restaurant",
"pickup_info": {
"pickup_datetime": "2024-09-18T22:25:19.552000Z",
"store_name": "Auto Delivery Enabled DoorDash Drive",
"store_address": "19 North Park Avenue, Rockville Centre, NY 11570",
"pickup_notes": null,
"estimated_pickup_at": null
},
"customer_info": {
"first_name": "first_name test",
"last_name": "last_name test",
"phone_number": "+12345677877",
"email": null
},
"drop_off_info": {
"drop_off_address": "19 North Park Avenue, Rockville Centre, NY 11570, US",
"drop_off_datetime": null,
"drop_off_notes": "Drop-off Notes",
"estimated_dropoff_at": null
},
"charges": {
"total": "55.0",
"delivery_fee": "9.75",
"delivery_tips": "10",
"subtotal": 133.0
},
"status": "new",
"created_at": "2024-10-09T07:44:21.885334Z",
"delivery_provider_id": "doordash_drive",
"courier_info": null,
"delivery_at": null,
"canceled_at": null,
"accepted_at": null,
"is_mock_delivery": false
}