Proxy API (deprecated)
The Proxy API will be removed in an upcoming release. It existed to expose the API through your WordPress site, back when there was no public API to call directly. There is now: the Joinotify API does the same without depending on your site being up, with more message types, scheduling and real delivery confirmation.
The routes still work for now. If you are still using them, see how to migrate below.
The Proxy API exposes REST endpoints on your own site that forward the send to Joinotify. An external system calls your domain; the plugin resolves the transport, the authentication and the queue.
It is useful for:
- Security — your Joinotify token never leaves your server; callers use a key of their own that you can rotate at any time.
- Simplicity — two endpoints with a minimal body, no need to learn the full API contract.
- Control — WordPress sits in the middle, so you can throttle, filter or log requests before forwarding them.
If the sending system already speaks HTTP with bearer authentication, calling the Joinotify API directly is simpler and does not depend on your site being up. The Proxy API exists for the cases where WordPress has to sit in the middle.
How to migrate
The destination is the Joinotify API, called directly by the system that sends. The key is the same one the plugin already holds — take it from Joinotify → Settings → Integrations, on the WhatsApp card, or issue your own in the dashboard.
| Before | Now |
|---|---|
POST https://yoursite.com/wp-json/joinotify/v1/send-message/text | POST https://api.joinotify.com/messages with {"type":"text"} |
POST .../send-message/media | POST https://api.joinotify.com/v1/{phone_number_id}/messages |
X-API-Key header | Authorization: Bearer sk_live_… header |
receiver / message | to / body |
curl -X POST https://api.joinotify.com/messages \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{ "type": "text", "to": "5511910203040", "body": "Hello!" }'
What you gain: the message types the Proxy API never exposed (template, buttons, list,
carousel, media by id), scheduling with cancellation
and real delivery status — the Proxy API only
ever said the message was accepted.
What you lose: WordPress stops sitting in the middle, so any filtering or logging you hung there has to move.
Telling whether anyone still uses it
Every proxy response carries two headers:
Deprecation: true
X-Joinotify-Deprecation: The Joinotify Proxy API is deprecated and will be removed in an
upcoming release. Migrate to the Joinotify API (official WhatsApp Cloud API).
And every call is written to the debug log as a WARNING. That is how you find which
integration still points at the old shape before the routes go away.
Enabling it
Under Joinotify → Settings → General, in the Proxy API card:
| Field | Default | What it does |
|---|---|---|
| Enable Proxy API | off | Registers the endpoints on the site |
| Text route | send-message/text | Path of the text message route |
| Media route | send-message/media | Path of the media message route |
| API key | empty | Value expected in the X-API-Key header |
The routes live under the joinotify/v1 namespace. With the default values, the final addresses
are:
https://yoursite.com/wp-json/joinotify/v1/send-message/text
https://yoursite.com/wp-json/joinotify/v1/send-message/media
The routes are only registered with the Proxy API enabled — and since 2.4.0 it ships disabled on new installs. Without enabling it, WordPress answers 404.
Authentication
Send the configured key in the X-API-Key header. Without it — or with a different value — the
response is 403.
Sending a text message
curl -X POST https://yoursite.com/wp-json/joinotify/v1/send-message/text \
-H 'X-API-Key: cb9sDT9MRjlMnBIQglneN6uEEKxvrcpW' \
-H 'Content-Type: application/json' \
-d '{
"sender": "5541912345678",
"receiver": "5511910203040",
"message": "Your order #1042 is confirmed.",
"delay": 60
}'
| Field | Required | Description |
|---|---|---|
sender | yes | Sender phone in international format |
receiver | yes | Recipient phone in international format |
message | yes | The message text |
delay | no | Wait in seconds before sending. Without it, the send is immediate |
Sending a media message
curl -X POST https://yoursite.com/wp-json/joinotify/v1/send-message/media \
-H 'X-API-Key: cb9sDT9MRjlMnBIQglneN6uEEKxvrcpW' \
-H 'Content-Type: application/json' \
-d '{
"sender": "5541912345678",
"receiver": "5511910203040",
"media_type": "document",
"media_url": "https://yoursite.com/wp-content/uploads/2026/07/manual.pdf",
"caption": "Here is the product manual."
}'
| Field | Required | Description |
|---|---|---|
sender | yes | Sender phone in international format |
receiver | yes | Recipient phone in international format |
media_type | yes | image, video, document or audio |
media_url | yes | File URL, on your site or external |
caption | no | Media caption |
delay | no | Wait in seconds before sending |
Accepted formats per type
- Image
- Video
- Document
- Audio
.jpeg · .png · .gif · .bmp · .webp
.mp4 · .3gp · .avi · .mpeg
.pdf · .doc · .docx · .xls · .xlsx · .ppt · .pptx · .txt
.mp3 · .mpeg · .ogg · .oga · .wav · .amr
To allow other formats, use the Joinotify/Validations/Get_Mime_Types filter — see
Developer resources.
Example: announce a published post
The snippet below goes in the theme's functions.php or in a snippets plugin such as
WPCode. It calls the site's own
Proxy API, reusing the helpers that resolve the address and the key.
add_action( 'publish_post', 'meumouse_announce_published_post' );
/**
* Sends a text message through the Proxy API when a post is published.
*
* @param int $post_id | ID of the published post.
*/
function meumouse_announce_published_post( $post_id ) {
if ( get_post_type( $post_id ) !== 'post' ) {
return;
}
$post = get_post( $post_id );
$message = sprintf(
"Hey, a new post just went live!\n\nTitle: %s\nAuthor: %s\nLink: %s",
$post->post_title,
get_the_author_meta( 'display_name', $post->post_author ),
get_permalink( $post_id )
);
$response = wp_remote_post( joinotify_proxy_api_text_message_text_endpoint(), array(
'headers' => array(
'Content-Type' => 'application/json',
'X-API-Key' => joinotify_get_proxy_api_key(),
),
'body' => wp_json_encode( array(
'sender' => joinotify_get_first_sender(),
'receiver' => '5511910203040',
'message' => $message,
) ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
error_log( 'Failed to send the text message: ' . $response->get_error_message() );
}
}
When the code already runs on WordPress, you can skip the HTTP round trip and call
joinotify_send_whatsapp_message_text() directly. The Proxy API is for callers outside the
site.
The 24-hour window applies here too
With the Cloud API transport, a free-form text message is only delivered inside the 24-hour window. Outside it, an approved template is required — and the Proxy API does not expose template sending. See Delivering through Joinotify Cloud.