Next Restaurant 6.1.0: move your data in, run payroll, and connect other systems Next Inventory 6.2.0: a REST API and webhooks for your other systems Next DB 6.1: Auto-Updating Tables, Printing, Phone Layout and SEO Next Task 6.0.0: a task manager for Joomla Next Inventory 6.1.1: smoother Check Out, no more list limits, and much faster PHP2Shell: Is Your Joomla Site Safe? What to Do Today Introducing Next Boards: Kanban project and task boards for Joomla Building the Future of Joomla Extensions
NextSoftware

Setting up webhooks

Outbound events. When something happens in Next Restaurant — an order is placed, a payment is captured, a table is booked, an item runs out — an HTTP POST is sent to every webhook you set up for that event, so another system can react without polling.

Since 6.1 each webhook is its own record: a name, a URL, its own signing secret, its own list of events, and an on/off switch.

Configure them under Configuration → Webhooks. (Before 6.1 this was part of the Integrations screen; the REST API now has its own screen.)


Setting up

  1. Enable the API app under Apps. Webhooks belong to it.
  2. Go to Configuration → Webhooks and press New webhook.
  3. Give it a name (which system receives it) and the endpoint URL.
  4. Leave Signing secret empty to have one made, or paste your own.
  5. Tick the events it should receive. All are ticked to start with.
  6. Press Save. The webhook's secret is shown straight away: copy it into the receiving system.
  7. Press the test button (the paper plane) on the webhook's row. A signed ping is sent to that webhook alone, and the message says what it answered.

The first webhook you save also creates the retry task if it does not exist (see below).

The webhooks table

The Endpoints tab: each webhook with its events, secret, delivery counts and switch

Column What it shows
Name The name, with the URL underneath
Events The events it receives, or All events
Signing secret The last four characters. Amber until someone has copied it. Show and copy reveals it; Make a new secret replaces it
Deliveries How many are in the log; amber = waiting to retry, red = failed
Status Switch the webhook off and on
Actions Show its deliveries, send a test, edit, delete

Editing a webhook with the secret field left empty keeps its secret. Deleting a webhook deletes its delivery log too.

Updating from 6.0

6.0 kept one list of URLs, one secret and one event filter. The update turns each URL into its own webhook, signed with the same secret and receiving the same events, so receiving systems keep working without any change.


Choosing events

Events are grouped as on the screen: Orders, Payments, Reservations, Menu & stock and Customers. Tick a group to take all of its events, or tick them one by one. The full list, with what each carries, is in Payload data.

Select only the events the receiving system actually uses. A webhook needs at least one event.

A group whose app is switched off under Apps is not shown: nothing in it can happen.


The delivery queue

Every event is first queued, then sent:

  1. The first attempt is made as soon as the request that caused the event has finished. On PHP-FPM the guest's page has already been sent by then, so a slow endpoint never slows down an order. On other server setups the attempt still happens at the end of the request.
  2. Your endpoint must answer with any 2xx status within 5 seconds. That marks the delivery delivered.
  3. Anything else is retried — another status, a timeout, a refused connection — after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours and 24 hours. After the 8th failed attempt the delivery is marked failed and not tried again.
  4. Answering 410 Gone stops it at once. Use it when an endpoint has been retired on purpose.

Every retry carries the same webhook-id and the same body as the first attempt: to your consumer it is the same event, delivered again. Only webhook-timestamp and the signature are fresh, so a retry passes a replay check. See Verifying signatures.

Switching a webhook off cancels its waiting deliveries; they are never sent. Deleting it removes them with its log.

A webhook that cannot be reached at all (no connection, DNS failure) is not tried again in the same run: its other deliveries wait for the next run instead of each timing out in turn.

Switching the API app off pauses the queue: nothing new is queued, and waiting deliveries are held without using up their attempts. They go out when the app is switched back on.

Events are delivered at least once and in no guaranteed order. A retry can arrive after a later event about the same order. Dedupe on webhook-id, and compare data.updated_at before overwriting your copy of a record.


The retry task

Retries are sent by a Joomla scheduled task, Next Restaurant: Send webhook retries, run by the Task - Next Restaurant Webhooks plugin. Installing or updating Next Restaurant creates the task, set to run every minute, and enables the plugin. If the task is missing, saving the first webhook or switching the API app on creates it, once.

The Health tab shows whether the plugin and the task are on. If the plugin is off, an Enable it button switches it on, for a user Joomla allows to change plugins. Anyone else sees a link to the plugin and is told to ask a Super User. The Apps screen shows the same warning on the API card, with a Repair button.

Without that task running, the first attempt still happens but a failed delivery is never retried. Joomla runs scheduled tasks in one of two ways:

  • Lazy scheduler (the default): tasks run when someone visits the site. On a quiet site, retries can be late.
  • Cron: a server cron job calls Joomla's scheduler on a timer. Retries run on time. See System → Scheduled Tasks → Options for the cron command.

To check it, or recreate it if it was deleted: System → Scheduled Tasks. The task should be listed and published. To recreate it, press New, choose Next Restaurant: Send webhook retries, set the interval to every minute and save. If it is not offered, enable the Task - Next Restaurant Webhooks plugin under System → Plugins first.

The same task also clears old records: finished deliveries after the retention period (30 days unless you change it, see below), Idempotency-Key records after 24 hours, and API rate-limit counters after a day. On sites without the task, one request in a hundred does this housekeeping after its response.

When retries are more than 15 minutes overdue, the Webhooks screen shows a warning that the task is not running, with a Retry due now button that sends every delivery that is due, immediately.


Delivery log

The Health tab: plugin, retry task, webhooks, secrets and the first successful delivery

The Deliveries tab lists every delivery, newest first, a page at a time, and refreshes every 15 seconds while it is open. Show its deliveries on a webhook's row opens it filtered to that webhook (remove the chip to see all). Filter by status:

Status Meaning
Waiting to retry An attempt failed; the next one is scheduled. Hover the status to see the HTTP status, the error and when the next try is due
Delivered Your endpoint answered 2xx
Failed 8 attempts failed, or the endpoint answered 410 Gone
Cancelled The webhook was switched off or deleted before the delivery could be sent

Each row also shows the webhook's name (hover for the URL), the number of attempts, the last HTTP status, the last error, whether the delivery was signed and under which schemes, and the delivery ID. The delivery ID is the same value the consumer saw in webhook-id, so "did you receive this one?" is a question with an answer on both sides.

Resend sends a delivery again now, whatever state it ended in — for example after fixing an endpoint that failed for a day. It is the same event with the same webhook-id, so a consumer that dedupes will not process it twice.

Clear log removes every delivered, failed and cancelled delivery. Deliveries still waiting are kept.

Keep the delivery log (days), on the Endpoints tab, sets how long finished deliveries are kept: 1 to 365 days, 30 by default. Lowering it removes the older rows at once. The Health tab shows the log's size and its oldest row.


Choosing endpoints

  • The URL must be a public address. A webhook is a request your server makes, so Next Restaurant refuses URLs that point at the server itself or at a private network: localhost, 127.0.0.1, 10.x, 192.168.x, 169.254.169.254 and their IPv6 forms, and URLs with a user name and password in them. This is checked when you save and again on every send, and a send goes to the address that was checked, without following redirects.
  • Receiving system on your own network? A Super User can switch on Allow webhooks to addresses on private networks on the Endpoints tab. Leave it off otherwise.
  • Use HTTPS. Payloads carry order and guest data.
  • Respond quickly. Acknowledge receipt with a 2xx and do the slow work afterwards; a reply that takes more than 5 seconds counts as a failure and is retried.
  • Be idempotent. Dedupe on webhook-id (or the body's id, the same value). It is stable for one event across every endpoint and every retry.

Webhooks versus the API

They solve different problems and are usually used together:

Use Reach for
"Tell me when an order is placed" Webhooks
"Give me the current menu" REST API
"Place an order from my kiosk" REST API
"Keep my system in sync" Webhooks to learn of changes, the API's updated_since lists to catch up after downtime

Each event's data is the same object the matching API GET returns, so you can usually act on the webhook alone.


Payment webhooks are different

The webhooks described here are outbound, from Next Restaurant to you.

Payment providers also send inbound webhooks — from Stripe or PayPal to your site — to confirm settlements. Those are configured per gateway, not here. See Payment Gateways.


See also

All Extensions