Skip to main content

Delivering through Joinotify Cloud

The plugin delivers messages through a channel. There are two WhatsApp channels, and they coexist on the same site:

ChannelHow it connectsMessage types
WhatsApp (Cloud API)Joinotify Cloud tokentext, media, audio and template
WhatsApp (Evolution)QR Code, over the legacy relaytext, media and audio

The Cloud channel talks to the Joinotify Cloud API — the same one any external integration uses — and behind it sits Meta's official Cloud API. It is the recommended path: the number is official, the send is signed by Meta and it does not depend on a live WhatsApp Web session on the server.

Setting it up​

Go to Joinotify → Settings → General, in the WhatsApp Cloud API card.

FieldWhat it does
Message transportAutomatic, Cloud API (official) or Evolution (legacy)
API tokenyour Joinotify Cloud token (sk_live_…)
Phone number IDthe phone_number_id used as the origin
WhatsApp Business Account IDthe waba_id that owns the templates

In Automatic mode — the default — the plugin uses the Cloud API whenever a token is available and falls back to Evolution when there is none. The other two values force a specific transport, which is handy for testing or for holding back the migration.

You probably don't need to fill anything in

When your license already has a Joinotify Cloud number provisioned, the token, the phone_number_id and the waba_id arrive with the license. The fields above are manual overrides: fill them in only to point the site at another number or another account. Left blank, whatever came with the license wins.

Where to find each identifier in the Joinotify Cloud dashboard is described in Quickstart.

The 24-hour window changes what you can send​

This is the difference you notice day to day. On the legacy relay, free-form text went out at any time. On the official Cloud API, outside the 24-hour window since the customer's last message, only an approved template is delivered — free-form text is rejected by Meta.

In practice:

  • Workflows replying to an ongoing conversation keep working exactly as before.
  • Workflows that start the conversation — "your order is out for delivery", "review your purchase 7 days later" — fall outside the window and need a template.

The full concept, with template categories and what each one costs, is in The 24-hour window and Templates.

There is no "Send template" action in the builder yet

The builder offers WhatsApp: text message and WhatsApp: media message. Template sending exists on the channel but not yet as a workflow node — for now it is reachable from code (see below) or straight through the Cloud API.

Sending a template from code​

Sending goes through the notification layer, which resolves the active channel:

functions.php or your own plugin
$result = joinotify_dispatch_notification( array(
'channel' => 'whatsapp_cloud',
'type' => 'template',
'sender' => joinotify_get_first_sender(),
'receiver' => '5541987111527',
'meta' => array(
'template_name' => 'order_shipped',
'language' => 'en_US',
'components' => array(
array(
'type' => 'body',
'parameters' => array(
array( 'type' => 'text', 'text' => '1042' ),
),
),
),
),
) );

if ( ! $result->is_success() ) {
error_log( 'Template send failed: ' . $result->error );
}

The shape of components is the same as the API's — see Sending messages.

How the plugin picks the origin number​

The phone_number_id is resolved from the workflow's sender. When that number has no phone_number_id of its own mapped, the account default applies — the Phone number ID setting, or the value provisioned with the license.

Errors and retries​

A failed send is not thrown away: the message goes to the processing queue (Joinotify → Processing queue) and is retried. Configuration errors — invalid token, missing template, closed window — are not retried, because insisting would not change the outcome; they are recorded in the history and in the logs.

The most common production error is the closed window, recorded as window_closed_requires_template. The full code table is in Errors.

Pointing at another environment​

To test against something other than production, define the constant in wp-config.php:

wp-config.php
define( 'JOINOTIFY_CLOUD_API_BASE_URL', 'https://api.example.com' );

Without the constant, the plugin talks to https://api.joinotify.com.