Next Inventory 6.1.0: App Manager, dark mode, and more Joomla 6.1 "Nyota" Is Here Building the Future of Joomla Extensions
NextSoftware
Next Restaurant — Documentation

Webhook events

Outbound events. When something happens in Next Restaurant, an HTTP POST is sent to the endpoints you configure — so another system can react without polling.

Webhooks tell you an order changed; they do not carry the whole order. There is no endpoint to fetch an order back, so keep the response you got when you created it.

Configured in Integrations.

Delivered as POST with Content-Type: application/json.

Envelope

{
    "id": "msg_4e9c1b7a2f08d3516ac4be9017d2f5a3",
    "type": "order.placed",
    "event": "order.placed",
    "data": [],
    "timestamp": "2026-08-28T19:30:00+00:00"
}
Field Type Meaning
id string Unique id for this delivery. The same value as the webhook-id header — dedupe on it.
type string The event name.
event string The same name again, kept for integrations built before type existed.
data object Identifiers for what changed — not the whole order.
timestamp string ISO 8601, when the event was dispatched.

Signing

Each delivery carries webhook-signature in the form v1,<base64>, computed with HMAC-SHA256.

The signature covers the {webhook-id}.{webhook-timestamp}.{raw body}.

  • Two schemes are sent on every signed delivery and you verify either one, not both: the preferred webhook-signature (Standard Webhooks, base64) and the legacy X-NextRestaurant-Signature (sha256= + hex over the raw body only).
  • An endpoint URL is not a secret — it can be guessed, logged by a proxy or leak from a config file. Without verification, anyone who learns the URL can post fabricated orders to your integration.
  • Verify before parsing or acting on the body, not after. Compute the HMAC over the bytes as received: re-serialising the JSON first changes them and the check will fail. Compare with a constant-time function.
  • Reject a delivery whose webhook-timestamp is more than ~300 seconds old, before checking the signature. The legacy scheme has no timestamp in what it signs, so it cannot tell a replay from a fresh delivery.
  • A whsec_-prefixed secret is base64: the HMAC key is the decoded bytes. A hand-typed secret is used as-is.
  • With no secret set, deliveries go out unsigned — both signature headers are simply absent, while webhook-id and webhook-timestamp are still sent. This is the state a new install ships in.

Verify a Standard Webhooks signature in PHP

$body = file_get_contents('php://input');
$id   = $_SERVER['HTTP_WEBHOOK_ID'] ?? '';
$ts   = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';

// Reject stale deliveries before doing any crypto.
if (!$ts || abs(time() - (int) $ts) > 300) {
    http_response_code(400);
    exit;
}

$secret   = str_starts_with($MY_SECRET, 'whsec_')
    ? base64_decode(substr($MY_SECRET, 6))
    : $MY_SECRET;
$expected = 'v1,' . base64_encode(hash_hmac('sha256', "$id.$ts.$body", $secret, true));

$ok = false;
foreach (explode(' ', $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '') as $candidate) {
    // Several signatures may be present during a key rotation.
    if (hash_equals($expected, $candidate)) {
        $ok = true;
    }
}

if (!$ok) {
    http_response_code(401);
    exit;
}

Delivery

There are no retries. A delivery that fails is not repeated.

Integrations shows recent delivery attempts — whether an endpoint received an event, how it responded, whether it was signed and under which schemes, and the delivery id. It is the first place to look when an integration "didn't get" something.

  • There are no retries. One attempt per endpoint with a five-second timeout. An endpoint that is down, slow, or answers outside the 2xx range loses that event permanently — treat webhooks as a fast path, not a guaranteed ledger, and reconcile from your own records if a gap would matter.
  • Be idempotent. Dedupe on webhook-id, which is stable for one event across every endpoint it is sent to, so a consumer subscribed twice can tell the second copy is not a second event.
  • Respond quickly. Acknowledge receipt and do the slow work asynchronously.
  • The endpoint must be reachable from your server over HTTPS. A URL on a private network your Joomla host cannot reach will never receive anything.
  • Ignore fields you do not recognise. New fields are added to payloads over time.

Select only the events you actually consume. Every selected event is delivered to every configured endpoint. Selecting none means all of them, not none.

Events

Event When
order.placed A new order is created, on any channel
order.updated An existing order changes
order.status_changed An order moves to a new status
order.cancelled An order is cancelled, with the reason
ping You press Test webhook — for connectivity checks only

All Extensions