Event Catalogue
This page lists every event you can subscribe to, when it is sent, and what its data contains.
Envelope
Every event is sent as JSON with the same shape:
{
"id": "evt_9c1f0b6a2d4e8f7a3b5c1d09",
"type": "order.paid",
"api_version": "2026-10-01",
"created_at": "2026-10-11T03:04:05.123Z",
"shop_id": 12,
"data": { "order": { } }
}
| Field | Meaning |
|---|---|
id | Unique event ID. It stays the same across retries and redeliveries |
type | Event type, see the table below |
api_version | Version of the data shape |
created_at | When the event was created (UTC) |
shop_id | Your shop ID |
data | The event content; the key depends on the event type |
Event list
| Event | Sent when | data key |
|---|---|---|
order.created | An order is created (storefront checkout, POS sale, booking or rental order) | order |
order.paid | Status becomes Paid (also at creation when paid immediately, for example POS cash) | order |
order.canceled | Status becomes Canceled (stock, coupon, and points were restored) | order |
order.expired | An unpaid order expires | order |
order.status_changed | Every status change (not creation): Paid, On delivery, Delivered, Canceled, Payment expired | order, with previous_status |
refund.created | A refund is recorded | refund |
stock.low | An item drops to or below its reorder point (once per item, branch, and day; same rule as the in-app alert) | item |
stock.adjusted | A stock movement is applied: manual adjustment, stock count, branch transfer, purchase receipt (not sales) | adjustments[] |
purchase_order.received | Goods are received against a PO | purchase_order, receipt |
booking.created | A booking slot is created | booking |
booking.rescheduled | A booking is moved | booking, with previous (old date and time) |
booking.canceled | A booking is canceled | booking |
booking.no_show | A booking is marked no-show (manual or automatic) | booking |
review.created | A customer submits a review (any moderation status; the status field is PUBLISHED or PENDING) | review |
customer.created | A customer registers or is created by staff | customer |
product.created | A product is created | product |
product.updated | A meaningful field changed: name, description, category, price, discounts, wholesale, status, SKU, barcode, weight, flags, reorder point, stock mode, rental fields. Not stock counters, timestamps, or image order | product |
product.deleted | A product is deleted | product (id, name, SKU, deleted_at) |
webhook.test | Only from the test button; cannot be subscribed to | order (sample) |
Choosing ["*"] (All events) means every event above, including new ones.
Example: order.paid
{
"order": {
"id": 1001,
"sales_no": "INV-0001",
"status": "PAID",
"branch_id": 1,
"customer": { "id": 9, "fullname": "Sari", "email": "sari@example.com", "phone": "08123456789" },
"items": [
{
"id": 5001, "product_id": 77, "product_variant_id": null,
"product_name": "Kopi 250g", "variant_name": null, "sku": "KOPI-250",
"qty": 2, "price": 50000, "total_price": 100000, "notes": null, "refunded_qty": 0,
"booking_date": null, "rental_start_date": null, "rental_end_date": null
}
],
"subtotal": 100000, "coupon_price": 0, "delivery_fee": 10000, "fee": 0,
"tax_amount": 0, "service_charge_amount": 0, "points_spend": 0,
"grand_total": 110000, "refunded_amount": 0, "refund_status": null,
"delivery_address": null, "deposit_amount": 0, "deposit_status": null, "balance_due": 0,
"created_at": "2026-10-11T03:00:00.000Z",
"updated_at": "2026-10-11T03:04:05.000Z"
}
}
The above is the value of data. For order.status_changed the shape is the same plus "previous_status": "PAYMENT-WAITING" inside order.
What is never sent
- passwords, salts, tokens, or hashes of any kind
- cost data (
cost_price, cost values, margins) in any event - payment gateway metadata
- customer data is limited to id, name, email, and phone
The system also strips forbidden keys anywhere in the document as a last line of defence.
Ordering and duplicates
- Ordering between events is not guaranteed. For example, two events close together may arrive reversed. Use the timestamps in the data, not arrival order.
- An event can arrive more than once. Store the
idof events you have processed and ignore repeats. - The
idstays the same across retries, redeliveries, and replays. TheX-Etalasse-Delivery-Idheader differs per delivery, so do not use it to deduplicate.
Headers sent
| Header | Content |
|---|---|
X-Etalasse-Event-Id | Event ID |
X-Etalasse-Event-Type | Event type |
X-Etalasse-Delivery-Id | Delivery ID |
X-Etalasse-Attempt | Attempt number (starts at 1) |
X-Etalasse-Signature | Signature, see Verifying signatures |
User-Agent | Etalasse-Webhooks/1.0 |
The body is sent as Content-Type: application/json; charset=utf-8, compact JSON, well under 256 KB.