eatsy Webhooks
Overview
eatsy can send webhook notifications to your business when order events happen. Webhooks let your system receive order updates automatically without polling an API.
To receive webhooks, provide eatsy with an HTTPS webhook URL. eatsy will send a POST request to that URL whenever a subscribed event occurs.
eatsy will also generate and provide your business webhook secret. Your endpoint should use this secret to verify that webhook requests came from eatsy.
Webhook Notifications
Webhook notifications are sent as JSON over HTTPS.
Each notification includes:
- A top-level event type.
- The eatsy business ID.
- The related order ID.
- Event data in the
dataobject. - Request headers that identify the event and help you verify the sender.
Your endpoint should acknowledge receipt with a 2xx response.
Event Types
eatsy currently supports these webhook event types:
| Event type | Description |
|---|---|
order.created | An order was created. |
order.paid | An order is paid in full. If the order requires a courier, delivery has been created successfully and assigned before this event is sent. Only orders that meet these requirements are presented to restaurants. |
order.refunded | An order payment was refunded. |
order.canceled | An order was canceled. |
For now, order.paid is the event guaranteed to include the full order object in data.
Request Headers
Every webhook request includes these headers:
Content-Type: application/json
X-eatsy-Webhook-Secret: <your-business-webhook-secret>
X-eatsy-Event-Id: <event-id>
X-eatsy-Event-Type: <event-type>
X-eatsy-Business-Id: <business-id>| Header | Description |
|---|---|
Content-Type | Always application/json. |
X-eatsy-Webhook-Secret | Secret generated by eatsy for your business. Use it to verify the request. |
X-eatsy-Event-Id | Unique webhook event ID. Use this for idempotency. |
X-eatsy-Event-Type | Event type, such as order.paid. |
X-eatsy-Business-Id | eatsy business ID associated with the event. |
Payload Format
Webhook requests use this top-level JSON shape:
{
"type": "order.paid",
"business_id": "7e15147b-89b0-4abe-8a29-5bf7a9acb525",
"order_id": "41282d6d-f3b2-43a0-be66-daf16decebf4",
"data": {}
}| Field | Description |
|---|---|
type | Webhook event type. |
business_id | eatsy business ID. |
order_id | Related eatsy order ID. |
data | Event data. For order.paid, this is the full order object. |
Example Order Paid Payload
This example shows the maximum current shape of an order.paid payload.
{
"data": {
"items": [
{
"image": "https://geuhlojitrsdezslcoxx.supabase.co/storage/v1/object/public/products/7e15147b-89b0-4abe-8a29-5bf7a9acb525/1766618561109-y0bit7i-fries.jpeg",
"options": {
"date": [
{
"name": "DATE OPTION",
"value": "2026-05-26"
}
],
"text": [
{
"name": "TEXT OPTION",
"value": "value of text option"
}
],
"number": [
{
"name": "NUMBER OPTION",
"value": 1234
}
],
"checkbox": [
{
"name": "CHECKBOX",
"choices": [
{
"price": 1000,
"choice": "CHOICE 1"
},
{
"price": 0,
"choice": "CHOICE 2"
}
]
},
{
"name": "CHECKBOX with quantity",
"choices": [
{
"price": 1000,
"choice": "choice 1",
"quantity": 2
}
]
}
],
"selection": [
{
"name": "SELECTION OPTION",
"choice": {
"price": 1000,
"choice": "CHOICE 1"
}
},
{
"name": "Selection with quantity",
"choice": {
"price": 1000,
"choice": "choice 1",
"quantity": 4
}
}
]
},
"quantity": 2,
"total_price": 3000,
"product_variant_name": "Sandwich - Fries"
},
{
"image": null,
"options": {},
"quantity": 1,
"total_price": 1000,
"product_variant_name": "Producto 1"
}
],
"client": {
"email": "asolmon88@gmail.com",
"last_name": "",
"first_name": "Ariel",
"phone_number": "+50683117124"
},
"order_id": "41282d6d-f3b2-43a0-be66-daf16decebf4",
"created_at": "2026-05-06T05:21:43.774078+00:00",
"receipt_url": null,
"order_status": "pending",
"order_options": [
{
"type": "select",
"value": {
"price": 0,
"choice": "Coca cola"
},
"question": "Coca cola gratis incluida"
}
],
"tracking_link": "https://delivery.uber.com/cr/orders/17bb6af2-4511-457e-85a5-28a6d178d36c?tenancyOverride=uber%2Ftesting%2Fdirect%2F1b3fa1f7-10c6-56ce-9808-6cb1e6f2b7de",
"delivery_price": 0,
"products_price": 15000,
"delivery_method": {
"uid": "a926c50e-b6db-407c-b949-1422d8d4ecd8",
"name": "Express",
"require_courier": true
},
"pickup_ready_dt": "2026-05-06T05:42:10.094+00:00",
"uber_customer_id": "1b3fa1f7-10c6-56ce-9808-6cb1e6f2b7de",
"uber_delivery_id": "del_F7tq8kURRX6FpSim0XjTbA",
"discount_breakdown": {
"code": "DESCUENTO",
"title": "Descuento 1",
"ends_at": null,
"starts_at": "2026-02-19T14:51:45+00:00",
"applies_to": "orders",
"value_type": "percent",
"discount_id": "1c0b615b-1867-4da5-a5a1-f7eb82698d01",
"value_amount": 15,
"location_scope": "all",
"discount_amount": 2250,
"eligible_subtotal": 15000,
"order_total_after_discount": 12750,
"order_total_before_discount": 15000
},
"human_order_number": 236,
"pickup_deadline_dt": "2026-05-06T05:52:10.094+00:00",
"delivery_created_at": "2026-05-06T05:22:10.094+00:00"
},
"type": "order.paid",
"order_id": "41282d6d-f3b2-43a0-be66-daf16decebf4",
"business_id": "7e15147b-89b0-4abe-8a29-5bf7a9acb525"
}Order Data Fields
The data object for order.paid contains the order information your business can use for fulfillment.
| Field | Description |
|---|---|
data.order_id | Unique eatsy order ID. |
data.human_order_number | Human-friendly order number shown to the business. |
data.created_at | Order creation timestamp in ISO 8601 format. |
data.order_status | Current order status. |
data.products_price | Total price of products before delivery fees. |
data.delivery_price | Delivery fee charged for the order. |
data.order_options | Order-level options selected by the customer. |
data.client | Customer contact information. |
data.delivery_method | Delivery method selected for the order. |
data.items | Products and variants included in the order. |
data.tracking_link | Delivery tracking URL, when available. |
data.uber_delivery_id | Uber delivery ID, when the order uses Uber delivery. |
data.uber_customer_id | Uber customer ID, when available. |
data.pickup_ready_dt | Estimated time when the order should be ready for pickup. |
data.pickup_deadline_dt | Pickup deadline timestamp. |
data.delivery_created_at | Timestamp when delivery was created. |
data.discount_breakdown | Discount metadata and calculated discount totals, when a discount applies. |
data.receipt_url | Receipt URL, when available. |
Item Fields
Each object in data.items represents a product variant in the order.
| Field | Description |
|---|---|
image | Product image URL, or null. |
options | Product option groups selected by the customer. |
quantity | Quantity ordered. |
total_price | Item price value included in the order payload. |
product_variant_name | Product and variant display name. |
Item Option Groups
Item options can include these groups:
| Option group | Description |
|---|---|
date | Date-based option answers. |
text | Text option answers. |
number | Numeric option answers. |
checkbox | One or more selected choices. |
selection | A single selected choice. |
Some choices can include quantity when the option supports quantities.
Webhook Security
eatsy generates a unique webhook secret for your business.
Every webhook request includes the secret in this header:
X-eatsy-Webhook-Secret: <your-business-webhook-secret>Your endpoint must compare this header with the webhook secret provided by eatsy. If the value does not match, reject the request.
Example:
const expectedSecret = process.env.EATSY_WEBHOOK_SECRET;
const receivedSecret = request.headers.get("X-eatsy-Webhook-Secret");
if (receivedSecret !== expectedSecret) {
return new Response("Unauthorized", { status: 401 });
}The webhook secret does not protect your endpoint automatically. It only protects your endpoint if your application validates it before processing the request.
Use X-eatsy-Event-Id to make your webhook handler idempotent. If your system receives the same event ID more than once, it should avoid processing the same event twice.
Expected Response
Return any 2xx HTTP response when your service has successfully received the webhook.
Examples:
200 OK
202 Accepted
204 No ContentYour endpoint should return quickly. If processing the webhook requires slow work, acknowledge the request first and process the work asynchronously.
Do not return a 2xx response if your service did not safely receive the event.
Timeouts And Failed Deliveries
eatsy waits up to 10 seconds for your endpoint to respond.
A webhook delivery is considered failed if:
- Your endpoint returns a non-
2xxHTTP status. - Your endpoint does not respond within 10 seconds.
- Your endpoint cannot be reached.
Automatic retry behavior is currently in the works.
Set Up Your Webhook URL
To enable webhooks, provide eatsy with:
- Your HTTPS webhook endpoint URL.
- Any different endpoint URLs you want to use for specific locations.
- Whether you need the location ID included in the webhook payload.
- The technical contact responsible for maintaining the endpoint.
eatsy will generate and provide your business webhook secret.
Test Your Webhook
To test your webhook integration:
- Configure your webhook endpoint URL with eatsy.
- Confirm your endpoint accepts
POSTrequests with a JSON body. - Confirm your endpoint validates
X-eatsy-Webhook-Secret. - Create or pay a test order that should produce an
order.paidevent. - Confirm your endpoint receives the request.
- Return a
2xxresponse to acknowledge the webhook.
For debugging, you can temporarily use a request capture tool to inspect the full request body and headers. Replace the test URL with your production webhook URL before going live.
Troubleshooting
| Problem | What to check |
|---|---|
| No webhook received | Confirm the webhook URL is correct, uses HTTPS, and is enabled for the expected event type. |
| Webhook received but rejected | Confirm your endpoint is reading X-eatsy-Webhook-Secret and comparing it with the secret provided by eatsy. |
| Event received more than once | Use X-eatsy-Event-Id to make processing idempotent. |
| Delivery marked failed | Confirm your endpoint returns a 2xx response within 10 seconds. |
| Missing order details | For now, only order.paid is guaranteed to include the full order object in data. |