History, queue and resending
Two screens show what the plugin did with each message:
- Joinotify → History — what was sent, to whom, by which workflow and what happened.
- Joinotify → Processing queue — what is still to go out: steps waiting on a Delay and messages waiting for another attempt.
Message history
Each row is a message, with the status coming from Meta's real delivery confirmation:
| Status | Meaning |
|---|---|
| Sent | Meta accepted the message |
| Delivered | It reached the recipient's device |
| Read | The recipient opened it |
| Queued | It failed for a transient reason and is waiting for another attempt |
| Failed | It was not delivered. The Error column gives the reason, in plain words |
| Cancelled | A pending retry was cancelled by hand |
A row's details show the WhatsApp response and, for a template, the text the customer read, with the language and the value of each variable. Login codes (OTP) are always masked.
The history is always on
Since 2.7.0 the "Message history" switch is gone from Settings → About, and sites that had
turned it off started recording again. The history is what lets you resend a failure and answer
"did that message go out?". Anyone who needs to stop keeping a specific message uses the
Joinotify/Message_History/Should_Record filter.
How long the records are kept is chosen under Settings → About → History retention, from 30 days to "Keep forever".
Send again
A message that failed can be resent since 2.7.0 — from the row's Send again action, from the details window, or by selecting several rows, up to 50 at a time. A message whose automatic retry was cancelled can be resent too.
- Each resend is a single attempt, outside the retry queue, and becomes a new row with the source and workflow of the original.
- The original gets the Resent flag and stops offering a resend, so a failure is never sent twice by accident.
- Interactive, location, contact, reaction and sticker messages keep their full content in the history, so the resend sends exactly the same message.
No resend is offered for login codes, templates whose values were hidden from the history and messages with a local attachment, whose file the history does not keep.
Table, filters and export
The three tables — workflows, history and queue — have the Items per page selector (10, 25, 50, 100 or 200), remembered by the browser, and export to JSON:
- Export on a row downloads just that item; selected rows come out together.
- In the history and the queue, the toolbar button exports everything the current filters select when nothing is ticked. The history stops at the 5,000 most recent records and says so.
- A workflow exported from here is the same file the builder exports, and can be imported back.
Automatic retries
When WhatsApp refuses a message for a reason that may pass — a timeout, a send limit, an outage — Joinotify parks the message and tries again. This is set up under Settings → General → Delivery retries:
| Option | Values | Default |
|---|---|---|
| Maximum attempts | "Do not retry" or from 1 to 10 | 5 |
| First retry after | 5, 15, 30, 60 or 120 minutes | 30 minutes |
Each attempt waits twice as long as the previous one. A send refused for rate limiting (429) waits exactly the time the API reports, instead of the table above.
Configuration errors do not go into this queue, because insisting does not change the outcome: an invalid API key, a missing or refused template, a closed 24-hour window. They go straight to Failed, with the reason.
Processing queue
The queue shows each scheduled item with its workflow, the next run time and the actions still to run. An item can be dispatched now or cancelled, and the export includes each item's runtime data.
Nothing in this queue moves without WP-Cron — see Minimum requirements.
Debug log
With Debug mode switched on under Settings → About, the plugin also logs every delivered
message (code dispatch_sent) and, on every failure, WhatsApp's own explanation. The log opens in
the same tab, has its own retention and shows the context as indented JSON.