Joinotify

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:

StatusMeaning
SentMeta accepted the message
DeliveredIt reached the recipient's device
ReadThe recipient opened it
QueuedIt failed for a transient reason and is waiting for another attempt
FailedIt was not delivered. The Error column gives the reason, in plain words
CancelledA 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:

OptionValuesDefault
Maximum attempts"Do not retry" or from 1 to 105
First retry after5, 15, 30, 60 or 120 minutes30 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.