E-commerce Order Notifications
E-commerce notifications for new orders, refund requests, low inventory, and failed payments, routed to the right team via webhooks.
E-commerce notifications have different audiences - operations needs to know about new orders, finance cares about refunds, and warehouse cares about inventory. Alphorn routes each event to the right channel.
New order notification
fetch only rejects on network errors, so each example checks res.ok and throws on a 4xx/5xx response. Catch the error where you call these functions, so a failed notification doesn't break checkout.
async function onNewOrder(order) {
const res = await fetch("https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.ALPHORN_API_KEY}`,
},
body: JSON.stringify({
title: `New order #${order.id}`,
message: `${order.customerName} - ${order.items.length} items - ${order.currency} ${order.total.toFixed(2)}`,
priority: order.total > 500 ? 4 : 2,
tags: ["order", "new", order.total > 500 ? "high-value" : "standard"],
}),
});
if (!res.ok) throw new Error(`Alphorn responded ${res.status}`);
}Refund requests
async function onRefundRequested(order, reason) {
const res = await fetch("https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.ALPHORN_API_KEY}`,
},
body: JSON.stringify({
title: `Refund requested: Order #${order.id}`,
message: `Amount: ${order.currency} ${order.total.toFixed(2)}\nReason: ${reason}\nCustomer: ${order.customerEmail}`,
priority: 3,
tags: ["order", "refund"],
}),
});
if (!res.ok) throw new Error(`Alphorn responded ${res.status}`);
}Low inventory alerts
import os
import requests
def check_inventory(products, threshold=5):
for product in products:
if product.stock <= threshold:
requests.post(
"https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT",
headers={"Authorization": "Bearer " + os.environ["ALPHORN_API_KEY"]},
json={
"title": f"Low stock: {product.name}",
"message": f"Only {product.stock} units remaining (SKU: {product.sku})",
"priority": 4 if product.stock == 0 else 3,
"tags": ["inventory", "low-stock",
"out-of-stock" if product.stock == 0 else "warning"],
},
timeout=10,
).raise_for_status() # raises on 4xx/5xxFailed payment alerts
async function onPaymentFailed(order, error) {
const res = await fetch("https://app.alphorn.dev/n/V1StGXR8_Z5jdHi6B-myT", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.ALPHORN_API_KEY}`,
},
body: JSON.stringify({
title: `Payment failed: Order #${order.id}`,
message: `${error.message}\nCustomer: ${order.customerEmail}\nAmount: ${order.currency} ${order.total.toFixed(2)}`,
priority: 3,
tags: ["order", "payment-failed"],
}),
});
if (!res.ok) throw new Error(`Alphorn responded ${res.status}`);
}Routing examples
| Channel | Filter | Purpose |
|---|---|---|
| Slack (#orders) | Tags has any of new | New order feed |
| Slack (#finance) | Tags has any of refund | Refund requests for finance team |
| Slack (#warehouse) | Tags has any of inventory | Stock alerts for warehouse |
| Telegram | Tags has any of high-value | Founder gets notified on big orders |
Tags has any of order | Full order archive | |
| PagerDuty | Tags has any of out-of-stock | Escalate sold-out products |
Security Alerts
Get security alerts for failed SSH logins, root and sudo access, and application auth events, routed by priority to Slack, email, or SMS.
IoT & Sensor Alerts
Route IoT and sensor alerts to any channel: temperature thresholds, device offline detection, ESP32 and Arduino HTTP requests, and an MQTT bridge.