Developer Guide · Recipes
Recipe: e-commerce backend
Connect a custom store backend to Inboxi: order lifecycle messages on WhatsApp, delivery receipts flowing back to your system, order history for the AI agent, and abandoned-cart reminders.
If your store runs on Salla or Shopify, use the ready-made integrations (Salla, Shopify), which cover orders and abandoned carts without code. This recipe is for a custom backend: you call Inboxi when the order changes, and Inboxi tells you when messages are delivered or fail.
Architecture
Set up
- 1Connect WhatsAppConnect your WhatsApp Business number in Settings › Channels.
- 2Configure order eventsIn Settings › Automated Messages › Orders, configure
order.created,order.confirmed,order.shippedandorder.delivered: a session message and an approved Utility template for each, then switch them on. - 3Create a custom cart eventClick New Custom Event and create
custom.cart_reminderwith variablescustomer_nameandcart_link, plus a template with a URL button mapped tocart_link. - 4Create a key and a webhookCreate an API key, then a webhook for
message.delivered,message.readandmessage.failedpointing at your backend.
Order lifecycle messages
Trigger one event per state change from your order service. Keep the order in external data too, so the AI agent can answer “where is my order?”.
const EVENTS = {
created: 'order.created',
confirmed: 'order.confirmed',
shipped: 'order.shipped',
delivered: 'order.delivered'
};
async function onOrderStatusChanged(order) {
// 1. Keep the AI agent and the inbox up to date
await inboxi.post('/external-data', {
source: 'store',
dataType: 'orders_detail',
contactIdentifier: order.customer.phone, // international digits
externalId: `order_${order.id}`,
data: {
order_number: order.number,
status: order.status,
total: `${order.total} ${order.currency}`,
items: order.items.map(i => `${i.qty} × ${i.name}`),
tracking_url: order.trackingUrl || null
}
});
// 2. Message the customer
const event = EVENTS[order.status];
if (!event) return;
const { data } = await inboxi.post('/events/trigger', {
event,
phone: order.customer.phone,
data: {
customer_name: order.customer.firstName,
order_number: order.number,
total_amount: `${order.total} ${order.currency}`,
tracking_number: order.trackingNumber
}
});
await Orders.saveNotification(order.id, event, data.logId); // keep the logId
}order.* events require customer_name and order_number. Optional fields such as total_amount and tracking_number are available to your message and template mapping.Delivery status back into your backend
Store the WhatsApp outcome on the order so your support team (and your own dashboards) know whether the customer was reached.
app.post('/inboxi/webhook', verifyInboxi, async (req, res) => {
res.sendStatus(200); // acknowledge fast
const { event, data } = req.body;
if (event === 'message.delivered' || event === 'message.read') {
await Notifications.markByPhone(data.to, event.split('.')[1], data.timestamp);
}
if (event === 'message.failed') {
// e.g. the number is not on WhatsApp: fall back to SMS or email
await Notifications.markByPhone(data.to, 'failed', data.timestamp, data.error);
await fallbackToEmail(data.contact?.email, data.to);
}
});verifyInboxi is the signature check from Webhooks. Handle duplicates: a retried delivery carries the same messageId and status. To check one specific trigger instead, poll GET /api/v1/events/messaging/:logId/status with the saved logId.
Abandoned-cart reminders
Schedule the reminder when a cart is created, and cancel it on your side if the customer checks out first.
async function onCartUpdated(cart) {
if (!cart.customer?.phone || cart.reminderScheduled) return;
const sendAt = new Date(Date.now() + 60 * 60 * 1000).toISOString(); // in 1 hour
const { data } = await inboxi.post('/events/trigger', {
event: 'custom.cart_reminder',
phone: cart.customer.phone,
data: { customer_name: cart.customer.firstName, cart_link: `https://shop.example.com/cart/${cart.token}` },
sendAt
});
await Carts.update(cart.id, { reminderScheduled: true, reminderLogId: data.logId });
}Let support and the AI handle replies
- Customer replies to order messages land in the same WhatsApp conversation in the inbox, with the order data in the side panel.
- Register a
GETremote action such asget_order_status(callbackhttps://api.example.com/orders/{order_number}) and name it in your AI agent's instructions so it can fetch live tracking. See live lookups. - Register write actions like
resend_invoiceorcancel_orderfor agents to run from Settings › Developer Hub › Remote Actions.
Go-live checklist
| Check | Why |
|---|---|
| Every order event has an approved template | Most order updates are sent outside the 24-hour window. |
| Phones are stored in international format | Local formats are not deliverable. |
| Webhook signature and timestamp are verified | Prevents forged delivery updates. |
| Triggers are retried only on 429/5xx | Avoids duplicate messages to customers. |
| One API key per environment | Lets you rotate staging without touching production. |