Overview
The Kitchenhub API includes webhooks for incoming orders and store notifications. In order for your service to receive webhooks from Kitchenhub, set your webhook URL and rules via webhook API. It is also possible to set up multiple webhooks if you need them.
Type of webhook notifications
The following types of notification are supported: Order, MenuIntegrationStatus, IntegrationAccount, IntegrationAccountOnlineStatus, Delivery, Cook.
If you need to get real-time order notifications and update its status you have to get Order notification.
You can manage what type of orders you want to get and in which statuses by managing the setting of a webhook via webhook API. For example, you can use it, if you need to get orders only in new status and only if they are for delivery, but not for pickup.
You can also get other types of notifications when stores are going offline on the provider side, integration account is deactivated or menu integration status is changed.
Retry policy
If a webhook delivery fails, KitchenHub retries it once. Each event is delivered at most twice: the initial attempt and one retry.
A delivery is retried when:
- your endpoint responds with a 4xx or 5xx status;
the request fails, for example with a DNS, connection or SSL error, or a timeout. - A 2xx response is treated as delivered, and no retry is sent.
The retry is sent immediately after the failed attempt, with no delay. If the retry also fails, the event is not delivered again.
KitchenHub waits up to 10 seconds for each phase of the request: connect, write and read. Respond with a 2xx status as soon as the event is received, and continue processing asynchronously if it takes longer.
The same event may be delivered twice, so make your webhook handler idempotent.
Order notification
Event type is Order.
Event status may take one of the following values: OrderCreated, OrderUpdated.
The section Ordercontains the order data.
Example
{
"version":"2.0.0",
"event_data":{
"event_type":"Order",
"status":"OrderUpdated"
},
"order":{
"order":{
"id":6316634709688320,
"external_id":"99fc40a4-fa10-4703-9cfc-230c3aa5b287",
"number":"86f0bbdf",
"daily_number":11,
"type":"delivery",
"status":"cancelled",
"notes":null,
"paid":true,
"asap":true,
"add_disposable_items":false,
"prep_time_minutes":null,
"table_number":null,
"cancelled_by":"not accepted"
},
"provider":{
"id":"doordash_pos",
"name":"doordash_pos",
"merchant_id":"0ba73df4-bd12-421a-8e51-ef64c7350268",
"store_id":null
},
"store":{
"id":"e6f5206e-6939-4b3d-82c4-0e7bde09c4e8",
"name":"Nikki's store",
"partner_store_id":null
},
"customer":{
"name":"Test Customer",
"email":null,
"phone_number":"8552228111",
"phone_code":null
},
"items":[
{
"id":"3082240d-26ff-4462-94d4-bbfccdf42b52",
"partner_id":"3082240d-26ff-4462-94d4-bbfccdf42b52",
"name":"Test Item1",
"quantity":1,
"price":"2.0",
"base_price":"2.0",
"instructions":"Item for TEST",
"is_alcohol":false,
"options":[
{
"id":"c4949f63-a157-4bd0-9f84-f776d9dba390",
"partner_id":"c4949f63-a157-4bd0-9f84-f776d9dba390",
"name":"Test option1",
"quantity":1,
"price":"0.0",
"base_price":"0.0",
"modifier_name":"Test modifier1",
"options":[]
}
]
}
],
"delivery":{
"type":"provider",
"status":null,
"notes":null,
"address":{
"country":null,
"street":null,
"city":null,
"state":null,
"zipcode":null,
"unit_number":null,
"latitude":null,
"longitude":null
},
"full_address":null,
"courier":{
"name":null,
"photo_url":null,
"phone_number":null,
"status":"pending"
},
"service":null,
"cancellation_reason":null
},
"payment":{
"method":"ONLINE"
},
"charges":{
"subtotal":"2.0",
"tax":"0.17",
"tax_payout":"0.17",
"restaurant_tip_amount":"0.0",
"adjustment":null,
"tips":"0.0",
"discount":"0.0",
"total":"2.17",
"delivery_fee":null,
"service_fee":null,
"processing_fee":null,
"commission":null,
"payout":null,
"other_fee":{}
},
"timestamps":{
"placed_at":"2025-04-22T13:12:18.031201Z",
"created_at":"2025-04-22T13:12:18.589083Z",
"pickup_at":"2025-04-22T13:19:53Z",
"accepted_at":null,
"cancelled_at":"2025-04-22T13:18:02.289876Z",
"completed_at":null,
"delivery_at":null,
"scheduled_for":null
},
"location":{
"id":"e2634686-7717-41b7-b545-cb40da3a6c04",
"partner_location_id":null,
"name":"Test Location1",
"street":"100 N Centre Ave",
"city":"Rockville Centre",
"state":"NY",
"zipcode":"11570",
"lat":null,
"lon":null
}
}
}Menu integration status notification
Webhook type is MenuIntegrationStatus.
Event name may have only value MenuIntegrationStatusUpdated
The field menu_integration_status_data.status may take one of the following values: waiting, in_progress, completed, failed.
If the value of menu_integration_status_data.status is failedthen the field failed_reason will contain the reason description.
Example
{
"event_data":{
"webhook_type":"MenuIntegrationStatus",
"event_name":"MenuIntegrationStatusUpdated",
"version":1
},
"restaurant_data":{
"restaurant_id":"2b1561e5-74d8-49b4-9f09-c89f4f3f11f4",
"proxy_restaurant_id":"4beb760c-9bf9-4938-9acf-94f515785397",
"partner_store_id":null
},
"menu_integration_status_data":{
"partner_menu_id":"2b1561e5-74d8-49b4-9f09-c89f4f3f11f4",
"menu_name":"Test Menu",
"provider_id":"foodhub",
"status":"completed",
"failed_reason":null
}
}Integration account notification
Webhook type is IntegrationAccount.
Event name may have one of the values: AccountCreated, AccountConnectionStatusChanged, AccountDeactivated, AccountRemoved.
This webhook is triggered when an integration account (a connection of a store to a provider) is created, changes its connection status, or is removed.
Events
| Event name | When it is sent |
|---|---|
AccountCreated | A new integration account is created: the store starts connecting to a provider. connection_status is in_progress, or waiting_menu when the provider requires a menu and the store has none. |
AccountConnectionStatusChanged | The connection status changes to any value other than disabled, for example the connection is completed and the status becomes connected. |
AccountDeactivated | The connection status changes to disabled: the integration account is deactivated. Typically occurs when the provider blocks or disables the account, the integration connection is terminated by the provider, or the integration account is disabled in KitchenHub. |
AccountRemoved | The integration account is removed while the store stays in KitchenHub: the integration is disconnected by a user or through the KitchenHub API, or the account is replaced by a new one. connection_status is null. |
Connection status values
| Value | Meaning |
|---|---|
in_progress | The integration account is created and the connection is in progress, for example the restaurant has not yet authorized it on the provider's side. |
waiting_menu | The connection is on hold: the provider requires a menu, and the store had no menu in KitchenHub when the integration account was created. |
waiting | The connection is waiting for activation on the provider's side, for example a manual activation by the provider. |
waiting_menu_mapping | The POS is connected, and the menu has to be mapped to the POS catalog. |
action_required | The restaurant has to complete a step to finish the integration; connection_status_comment says what to do. |
rejected | The provider rejected the connection; connection_status_comment may carry the reason. |
connected | The connection is completed. |
disabled | The integration account is deactivated. |
Fields of integration_account_data
integration_account_data| Field | Type | Description |
|---|---|---|
connection_status_comment | string or null | Comment on the current status, when one is available: the deactivation reason reported by the provider (for example INVALID_CREDENTIALS), the reason of rejected, the step required for action_required. May be null, for example when the integration account was deactivated in KitchenHub. Always null for AccountRemoved. |
provider_id | string | Provider id in KitchenHub, for example ubereats, doordash, grubhub_pos. |
provider_store_id | string or null | Store id on the provider's side. Usually null until the connection is completed. |
connection_status | string or null | Connection status after the change, see Connection status values. null for AccountRemoved: the integration account no longer exists. |
account_id | string | Integration account id. |
dashboard_url | string or null | Reserved, currently always null. |
timestamp | string | When the change was saved in KitchenHub, ISO 8601 UTC with second precision: YYYY-MM-DDTHH:MM:SSZ. For AccountCreated it is the time the integration account was created, for AccountRemoved the time it was removed. |
Filtering
The filters of a webhook configuration are matched against the fields of integration_account_data, the same way order filters are matched against order fields. For example, {"provider_id": ["ubereats"]} delivers only the events of Uber Eats integration accounts. An empty filters object delivers every event.
A filter key is skipped when the event's field is null, so the event is delivered. AccountRemoved has connection_status: null, so {"connection_status": ["disabled"]} delivers deactivations and every removal.
Examples
An Uber Eats integration account was created, and the connection started:
{
"event_data":{
"webhook_type":"IntegrationAccount",
"event_name":"AccountCreated",
"version":1
},
"restaurant_data":{
"restaurant_id":"74659e82-ae12-4bba-b1e0-cb7124a2d100",
"proxy_restaurant_id":"3f7ac076-089d-4d00-97fa-bb3cd7640200",
"partner_store_id":null
},
"integration_account_data":{
"connection_status_comment":null,
"provider_id":"ubereats",
"provider_store_id":null,
"connection_status":"in_progress",
"account_id":"5f2c8e0b9a4d4c1e8b7a6d5c4b3a2f10",
"dashboard_url":null,
"timestamp":"2026-10-27T12:00:05Z"
}
}The connection was completed:
{
"event_data":{
"webhook_type":"IntegrationAccount",
"event_name":"AccountConnectionStatusChanged",
"version":1
},
"restaurant_data":{
"restaurant_id":"74659e82-ae12-4bba-b1e0-cb7124a2d100",
"proxy_restaurant_id":"3f7ac076-089d-4d00-97fa-bb3cd7640200",
"partner_store_id":null
},
"integration_account_data":{
"connection_status_comment":null,
"provider_id":"ubereats",
"provider_store_id":"f0e1d2c3-b4a5-4697-8879-6a5b4c3d2e1f",
"connection_status":"connected",
"account_id":"5f2c8e0b9a4d4c1e8b7a6d5c4b3a2f10",
"dashboard_url":null,
"timestamp":"2026-10-27T12:03:41Z"
}
}The provider invalidated the credentials of a DoorDash integration account:
{
"event_data":{
"webhook_type":"IntegrationAccount",
"event_name":"AccountDeactivated",
"version":1
},
"restaurant_data":{
"restaurant_id":"74659e82-ae12-4bba-b1e0-cb7124a2d100",
"proxy_restaurant_id":"3f7ac076-089d-4d00-97fa-bb3cd7640200",
"partner_store_id":null
},
"integration_account_data":{
"connection_status_comment":"INVALID_CREDENTIALS",
"provider_id":"doordash",
"provider_store_id":"111",
"connection_status":"disabled",
"account_id":"81673c1dd9e840ed99e82464ce4a00e2",
"dashboard_url":null,
"timestamp":"2026-10-27T15:20:00Z"
}
}The Uber Eats integration was disconnected in KitchenHub:
{
"event_data":{
"webhook_type":"IntegrationAccount",
"event_name":"AccountRemoved",
"version":1
},
"restaurant_data":{
"restaurant_id":"74659e82-ae12-4bba-b1e0-cb7124a2d100",
"proxy_restaurant_id":"3f7ac076-089d-4d00-97fa-bb3cd7640200",
"partner_store_id":null
},
"integration_account_data":{
"connection_status_comment":null,
"provider_id":"ubereats",
"provider_store_id":"f0e1d2c3-b4a5-4697-8879-6a5b4c3d2e1f",
"connection_status":null,
"account_id":"5f2c8e0b9a4d4c1e8b7a6d5c4b3a2f10",
"dashboard_url":null,
"timestamp":"2026-10-27T16:05:12Z"
}
}Integration account online status notification
Webhook type is IntegrationAccountOnlineStatus.
Event name may have only value AccountOnlineStatusChanged.
This webhook is triggered when the online status of an integration account (a store on a delivery provider) changes: the store is paused and goes offline, or is resumed and goes back online. The change may be made in KitchenHub or on the provider's side; the field online_status_data.source tells which.
Typically occurs when:
- A user pauses or resumes the store in the KitchenHub admin or app (
sourceisuser). - The store is paused or resumed through the KitchenHub public API,
PUT /v2/integration_accounts/{integration_id}/status/(sourceisapi). - KitchenHub pauses or resumes the store automatically: orders were cancelled or expired, the location was archived, the company was blocked (
sourceissystem). - The store is paused or resumed on the provider's side, by the restaurant in the provider's dashboard or tablet, or by the provider itself (
sourceisprovider). Supported for Uber Eats, DoorDash and Grubhub.
The webhook is not sent when a store is closed by its working hours or closing days: a schedule is not a status change.
When the event is sent
One event is sent per actual status change:
online->offlineandoffline->online;offline->offlinewhen the end of the pause changes, for example a new pause with a different duration or an extended pause.
Repeating the same status does not produce a new event.
DoorDash and GrubHub do not report when a paused store comes back online, so KitchenHub checks the status of paused DoorDash and GrubHub stores every 5 minutes. The online event may therefore arrive up to 5 minutes after the store was resumed, and its timestamp is the time the change was detected.
Fields of online_status_data
online_status_data| Field | Type | Description |
|---|---|---|
online_status | string | online or offline. |
account_id | string | Integration account id. |
provider_id | string | Provider id in KitchenHub, for example ubereats, doordash_pos, grubhub_pos. |
source | string | Who initiated the change: user, api, system or provider. See the values below. |
offline_reason_code | string or null | Machine-readable trigger of the pause. Set only when online_status is offline; null when the store goes online. See the values below. |
offline_reason | string or null | Human-readable reason of the pause, when one is available. For a pause made on the provider's side it carries the provider's own reason, for example PAUSED_BY_RESTAURANT. null when the store goes online or no text was given. |
pause_duration_seconds | integer or null | Seconds from timestamp until the store is expected to come back online. null when the store goes online or the pause has no scheduled end. A pause set in KitchenHub without a duration lasts until the end of the store's day, and the value is the number of seconds until then. |
timestamp | string | When the status change was confirmed, ISO 8601 UTC with second precision: YYYY-MM-DDTHH:MM:SSZ. For a change made on the provider's side it is the time of the provider's event, when the provider reports one. |
source values
source values| Value | Meaning |
|---|---|
user | A user changed the status in the KitchenHub admin or app. |
api | The status was changed through the KitchenHub public API. |
system | KitchenHub automation: auto-pause after cancelled orders, location archive, company block. |
provider | The change was made on the provider's side: by the restaurant in the provider's dashboard or tablet, or by the provider itself. |
offline_reason_code values
offline_reason_code values| Value | Meaning | Sent with source |
|---|---|---|
manual_pause | Manual pause by a user or through the API. | user, api |
order_cancellations | Automatic pause after orders were cancelled or expired. | system |
tablet_offline | Connection to the tablet app was lost. | system |
inactivity | A DoorDash store was paused for inactivity. | system |
location_archived | The location was archived in KitchenHub. | system |
company_blocked | The company account was blocked, for example for non-payment; applies to all its locations. | system |
provider_pause | The store was paused on the provider's side, by the restaurant or by the provider. | provider |
unknown | The reason was not provided or could not be mapped. | any |
Filtering
The filters of a webhook configuration are matched against the fields of online_status_data, the same way order filters are matched against order fields. For example, {"source": ["provider"]} delivers only the changes made on the provider's side, and {"online_status": ["offline"]} only pauses. An empty filters object delivers every event.
Examples
A user paused the store for one hour in the KitchenHub admin:
{
"event_data":{
"webhook_type":"IntegrationAccountOnlineStatus",
"event_name":"AccountOnlineStatusChanged",
"version":1
},
"restaurant_data":{
"restaurant_id":"acdf0ea1-3c42-4dae-aecf-12ad3a7d3000",
"proxy_restaurant_id":"723122c1-1c73-4433-a49e-ab1f452d8000",
"partner_store_id":null
},
"online_status_data":{
"online_status":"offline",
"account_id":"21229afe5048488cb09c105bac269000",
"provider_id":"ubereats",
"source":"user",
"offline_reason_code":"manual_pause",
"offline_reason":null,
"pause_duration_seconds":3600,
"timestamp":"2026-09-18T12:34:56Z"
}
}The store was resumed through the public API:
{
"event_data":{
"webhook_type":"IntegrationAccountOnlineStatus",
"event_name":"AccountOnlineStatusChanged",
"version":1
},
"restaurant_data":{
"restaurant_id":"acdf0ea1-3c42-4dae-aecf-12ad3a7d3000",
"proxy_restaurant_id":"723122c1-1c73-4433-a49e-ab1f452d8000",
"partner_store_id":"store-42"
},
"online_status_data":{
"online_status":"online",
"account_id":"5c0b0d1a4f0e4a6e9d3b2f1c8e7a6000",
"provider_id":"doordash_pos",
"source":"api",
"offline_reason_code":null,
"offline_reason":null,
"pause_duration_seconds":null,
"timestamp":"2026-09-18T13:00:02Z"
}
}The restaurant paused the store for 30 minutes in the Uber Eats dashboard:
{
"event_data":{
"webhook_type":"IntegrationAccountOnlineStatus",
"event_name":"AccountOnlineStatusChanged",
"version":1
},
"restaurant_data":{
"restaurant_id":"acdf0ea1-3c42-4dae-aecf-12ad3a7d3000",
"proxy_restaurant_id":"723122c1-1c73-4433-a49e-ab1f452d8000",
"partner_store_id":null
},
"online_status_data":{
"online_status":"offline",
"account_id":"21229afe5048488cb09c105bac269000",
"provider_id":"ubereats",
"source":"provider",
"offline_reason_code":"provider_pause",
"offline_reason":"PAUSED_BY_RESTAURANT",
"pause_duration_seconds":1800,
"timestamp":"2026-09-18T15:22:09Z"
}
}Delivery notification
Webhook type is Delivery.
Event name may take one of the following values: DeliveryCreated, DeliveryUpdated, QuoteCreated.
Example
{
"event_data":{
"webhook_type":"Delivery",
"event_name":"DeliveryUpdated",
"version":1
},
"restaurant_data":{
"restaurant_id":"ea5f5110-5455-4b35-9000-e12e994ad000",
"proxy_restaurant_id":"05594593-4626-4800-a1cf-3d08d8c93000",
"partner_store_id":"123"
},
"delivery_data":{
"id":123123,
"order_id":"cart-01",
"order_number":null,
"order_external_id":null,
"scheduled_order":false,
"delivery_order_id":"4a20d80e05944a8eaa21fa2558e31000",
"cancellation_reason":"store_closed",
"pickup_info":{
"restaurant_name":"Test Restaurant",
"restaurant_address":"368 E Campbell Ave, Campbell, California 95008",
"pickup_datetime":"2025-11-18T18:26:25.669000+00:00",
"pickup_notes":null,
"store_name":"Test Restaurant",
"store_address":"368 E Campbell Ave, Campbell, California 95008",
"estimated_pickup_at":null
},
"customer_info":{
"first_name":"Joe",
"last_name":"Doe",
"phone_number":"000111000",
"email":null
},
"drop_off_info":{
"drop_off_address":"368E Campbell Ave, Campbell, CA, 95008, USA",
"drop_off_datetime":null,
"drop_off_notes":"Dropoff notes",
"estimated_dropoff_at":null
},
"charges":{
"total":10,
"delivery_fee":6.25,
"delivery_tips":100,
"subtotal":null
},
"status":"cancelled",
"provider_id":null,
"courier_info":{
"id":null,
"name":"",
"phone_number":null,
"phone_code":null,
"photo_url":null,
"vehicle_type":null
},
"delivery_type":"restaurant",
"tracking_url":null,
"created_at":"2025-11-18T18:16:38.907966",
"delivered_at":null,
"canceled_at":"2025-11-18T18:54:30.040889",
"accepted_at":null,
"is_mock_delivery":false,
"items":[
{
"name":"Test item1",
"quantity":1,
"price":"9",
"is_alcohol":false
}
],
"store_id":"ea5f5110-5455-4b35-9000-e12e994ad000",
"virtual_brand_company_id":"Test Company",
"delivery_provider_id":"doordash_drive",
"delivery_at":null
}
}Cook notification
Webhook type is Cook.
Event name may have only value OrderCook.
Example
{
"event_data":{
"webhook_type":"Cook",
"event_name":"OrderCook",
"version":1
},
"restaurant_data":{
"restaurant_id":"adf7a8e2-50d9-4a74-bd81-969e86870000",
"proxy_restaurant_id":"9ab8cc76-367a-429f-9a7e-8504eab95000",
"partner_store_id":null
},
"cook_data":{
"order_id":123123,
"distance":500.0,
"order_number":"333444",
"provider_id":"doordash_pos"
}
}