Skip to content

Webhook events

Each delivery’s body is an envelope (event, data, timestamp, version), described in How webhooks work. This page lists what each event’s data holds.

The examples are formatted for reading, with made-up values. On the wire the JSON is compact, keys are sorted, and non-ASCII characters are escaped.

Event Sent when
ORDER_CREATED An order is placed.
PAYMENT_CAPTURED An online payment is captured.
ORDER_FULFILLED The last item on an order is dispatched.
RETURN_REQUESTED A customer asks to return items.
ORDER_ISSUE_REPORTED A customer reports a problem with a fulfilled order.
PRODUCT_UPDATED Staff save a product’s details.
STOCK_LOW The daily low-stock scan finds low stock.
CONSIGNMENT_DISPATCHED Goods leave for a retailer on a delivery challan.
CONSIGNMENT_SOLD A retailer reports selling or keeping a consignment item.
PING Staff send a test delivery.
CONSIGNMENT_OVERDUE Defined, but not sent at this build.

Sent when an order is placed: at storefront checkout, when staff finalise a draft order, or when an institutional customer accepts a quote with their purchase-order number. A cart with both in-stock and made-to-order items becomes two orders, and each sends its own event.

Field Type Meaning
number string Order number. Use it with order(number:).
status string Order status when the event was raised. At this build it is always UNCONFIRMED, even when the order is confirmed in the same step (for example cash on delivery). Read the current status with a query.
paymentMethod string PREPAID, COD or CREDIT.
segment string HOME, SCHOOL, COLLEGE or UNIVERSITY.
grandTotalPaise integer Order total in paise, the same as Order.grandTotal.paise.
currency string Always INR.
lines array One entry per order line.
lines[].sku string Variant SKU.
lines[].quantity integer Quantity ordered.
lines[].totalPaise integer GST-inclusive line total in paise, the same as OrderLine.total.paise.
{
"data": {
"currency": "INR",
"grandTotalPaise": 2499900,
"lines": [
{ "quantity": 1, "sku": "DEMO-SOFA-3S", "totalPaise": 2299900 },
{ "quantity": 2, "sku": "DEMO-CUSHION-SET", "totalPaise": 200000 }
],
"number": "RFO/2026-27/00000",
"paymentMethod": "PREPAID",
"segment": "HOME",
"status": "UNCONFIRMED"
},
"event": "ORDER_CREATED",
"timestamp": "2026-10-17T04:45:02.123456+00:00",
"version": "1"
}

Sent when an online payment is confirmed as captured by the payment gateway. It is sent once per payment:

  • a made-to-order order has two payments (advance and balance), so it sends two events;
  • one gateway charge that pays for a split cart sends one event per order, each with the same externalPaymentId.

It is not sent for cash-on-delivery or credit payments recorded by staff.

Field Type Meaning
orderNumber string The order this payment belongs to.
gateway string The payment gateway that took the money, for example razorpay.
amountPaise integer This payment’s amount in paise (not necessarily the order total).
externalPaymentId string The gateway’s own payment reference.
{
"data": {
"amountPaise": 2499900,
"externalPaymentId": "pay_DEMO00000000",
"gateway": "razorpay",
"orderNumber": "RFO/2026-27/00000"
},
"event": "PAYMENT_CAPTURED",
"timestamp": "2026-10-17T04:46:10.004211+00:00",
"version": "1"
}

Sent when a fulfilment covers the last unfulfilled item, so the order’s status becomes FULFILLED. That means shipped with a courier, sent with our delivery crew, or ready for pickup. It is not proof of delivery. Part shipments don’t send it.

data has the same fields as ORDER_CREATED, with status set to FULFILLED.

{
"data": {
"currency": "INR",
"grandTotalPaise": 2499900,
"lines": [
{ "quantity": 1, "sku": "DEMO-SOFA-3S", "totalPaise": 2299900 },
{ "quantity": 2, "sku": "DEMO-CUSHION-SET", "totalPaise": 200000 }
],
"number": "RFO/2026-27/00000",
"paymentMethod": "PREPAID",
"segment": "HOME",
"status": "FULFILLED"
},
"event": "ORDER_FULFILLED",
"timestamp": "2026-10-20T09:12:40.551870+00:00",
"version": "1"
}

Sent when a customer asks to return items from an order that has been fulfilled (fully or in part), or from a cancelled order some of whose items had already been sent. The request comes from the storefront or the returns assistant. There is no published query for returns, so this payload is all you get.

Field Type Meaning
orderNumber string The order the items came from.
returnId integer Our internal number for the return request. It is not a GraphQL ID.
reason string The customer’s own words. Treat it as personal data.
lines array Items to return.
lines[].sku string Variant SKU.
lines[].quantity integer Quantity to return.
{
"data": {
"lines": [{ "quantity": 1, "sku": "DEMO-SOFA-3S" }],
"orderNumber": "RFO/2026-27/00000",
"reason": "Example reason text.",
"returnId": 0
},
"event": "RETURN_REQUESTED",
"timestamp": "2026-10-25T06:00:00.000123+00:00",
"version": "1"
}

Sent when a customer reports a problem, such as damage or missing parts, with an order that has been fulfilled (fully or in part). There is no published query for issues.

Field Type Meaning
orderNumber string The order concerned.
issueId integer Our internal number for the issue. It is not a GraphQL ID.
type string DAMAGED_IN_TRANSIT, MISSING_PARTS, MANUFACTURING_DEFECT, WRONG_ITEM, ASSEMBLY_PROBLEM or OTHER.
description string The customer’s own words. Treat it as personal data.
{
"data": {
"description": "Example description text.",
"issueId": 0,
"orderNumber": "RFO/2026-27/00000",
"type": "MISSING_PARTS"
},
"event": "ORDER_ISSUE_REPORTED",
"timestamp": "2026-10-21T08:30:00.250000+00:00",
"version": "1"
}

Sent when staff save the product’s own details (name, description, brand, category, tax codes, product-level price and MRP, dimensions and similar fields). It is sent on every save, even if nothing changed. It is not sent when a product is created, published, unpublished or deleted, or for edits to variants (including a variant’s own price), media or stock.

Field Type Meaning
slug string The product’s slug. Use it with product(slug:). Saving a product can’t change it.
name string Product name. It may contain any script, for example Telugu.
status string DRAFT or PUBLISHED.
{
"data": {
"name": "టేకు చెక్క కుర్చీ",
"slug": "demo-teak-chair",
"status": "PUBLISHED"
},
"event": "PRODUCT_UPDATED",
"timestamp": "2026-10-17T04:45:02.123456+00:00",
"version": "1"
}

On the wire, that name arrives escaped:

{"data":{"name":"\u0c1f\u0c47\u0c15\u0c41 \u0c1a\u0c46\u0c15\u0c4d\u0c15 \u0c15\u0c41\u0c30\u0c4d\u0c1a\u0c40","slug":"demo-teak-chair","status":"PUBLISHED"},"event":"PRODUCT_UPDATED","timestamp":"2026-10-17T04:45:02.123456+00:00","version":"1"}

Sent when the daily low-stock scan finds stock at or below its threshold. The scan runs at 07:00 IST by default; staff can change the schedule. If nothing is low, nothing is sent. Only warehouses that sell online are scanned.

Field Type Meaning
items array Up to 50 rows, lowest available stock first. One row per variant per warehouse, so a SKU can appear more than once. The warehouse is not named.
items[].sku string Variant SKU.
items[].product string Product name.
items[].available integer Units on hand minus units reserved.
items[].threshold integer The low-stock threshold set for that stock row.
{
"data": {
"items": [
{ "available": 0, "product": "Demo Teak Chair", "sku": "DEMO-CHAIR-TEAK", "threshold": 2 },
{ "available": 1, "product": "Demo Three-Seater Sofa", "sku": "DEMO-SOFA-3S", "threshold": 3 }
]
},
"event": "STOCK_LOW",
"timestamp": "2026-10-17T01:30:00.418203+00:00",
"version": "1"
}

Sent when staff dispatch goods to a retailer on a delivery challan. If raising the event fails, the dispatch still goes ahead and no event is sent, so reconcile with consignments.

Field Type Meaning
number string Challan number.
dealer_id integer The retailer’s internal number. Build the Dealer ID from it to query: see Consignment to ERP.
unit_count integer Number of items on the challan.
total_value_paise integer GST-inclusive value of the goods at transfer price, in paise.
dispatched_at string or null When the goods left, ISO 8601 with a UTC offset.
{
"data": {
"dealer_id": 0,
"dispatched_at": "2026-10-17T05:30:00+00:00",
"number": "RFDC/2627/00000",
"total_value_paise": 8450000,
"unit_count": 6
},
"event": "CONSIGNMENT_DISPATCHED",
"timestamp": "2026-10-17T05:30:01.207346+00:00",
"version": "1"
}

Sent when a retailer reports that an item from consignment stock has gone: sold to a customer, or kept by the retailer themselves. The payload doesn’t say which. It is sent once per report; if the retailer’s app sends the same report again, no second event follows. If raising the event fails, the sale still stands and no event is sent, so reconcile with consignmentInvoices.

Field Type Meaning
sale_id integer Our internal number for the sale.
dealer_id integer The retailer’s internal number.
sku string Variant SKU of the item sold.
transfer_price_paise integer What we invoice the retailer for the item, in paise.
sold_at string or null When the retailer says it sold, ISO 8601 with a UTC offset.
{
"data": {
"dealer_id": 0,
"sale_id": 0,
"sku": "DEMO-BED-QUEEN",
"sold_at": "2026-10-18T12:05:00+00:00",
"transfer_price_paise": 2100000
},
"event": "CONSIGNMENT_SOLD",
"timestamp": "2026-10-18T12:05:03.880012+00:00",
"version": "1"
}

Sent when staff send a test delivery to one webhook. It goes to that webhook even if PING is not among its events. See Checking your receiver with PING.

Field Type Meaning
message string Always RaviFurniture webhook test.
{
"data": { "message": "RaviFurniture webhook test" },
"event": "PING",
"timestamp": "2026-10-17T04:45:02.123456+00:00",
"version": "1"
}

CONSIGNMENT_OVERDUE exists in the list of event types, so staff can tick it, but nothing sends it at this build. Don’t build anything that waits for it.

Payloads follow an additive-only rule: fields can be added, but existing fields are not removed or changed. Ignore fields you don’t recognise, and acknowledge (with 2xx) any event type you don’t handle.