Wow! Build your WhatsApp integration. Start free. Register Now
Channel content sync · WhatsApp API use case

WhatsApp channel publish when content goes live

Subscribers can see the same launch or promo in your WhatsApp channel as soon as the site or store publishes it, without someone copying text into the app. When your backend marks the content live, your worker can resolve the channel id and post the announcement through Whapi.Cloud. This use case shows integrators how to implement that flow through the WhatsApp API.

Triggered when CMS or store publishes getNewsletters, then sendMessageText
CMS or store publish screen beside a phone whose WhatsApp channel shows a new announcement with a subscriber notification.
Decorartive bubble
Use case

When to use this flow

The trigger is a backend publish event

Use this flow when a blog, product, promo, or CMS go-live event in own_backend should also update a WhatsApp Channel, not when you only reply to inbound chats.

The broadcast target is a WhatsApp Channel

Use this flow when the post goes to a channel JID, not when you need every member of a community to see a subgroup announcement.

You need the channel id before you send

Use this flow when the worker must read the channel list with getNewsletters to pick the correct JID, not when you already store that id in config.

WhatsApp channel on a phone showing a new announcement post with the standard channel notification banner.
Customer experience

Subscribers get the update

The website or store shows the new article or promo on time, but the WhatsApp channel still waits for someone to paste the same copy by hand.

After the flow runs, channel subscribers see the announcement in the channel and get the usual channel notification on their phones. Integrators build this result with the WhatsApp API.

Workflow

From publish event to channel post

1

Content publish succeeds in the backend

Your CMS, store, or scheduler signals that the article, product, or promo is live. A worker builds the announcement text and optional link for the channel body.

2

Resolve the target channel JID

GET /newsletters

getNewsletters returns your channels with metadata. Match the channel your campaign should update and take its id for the send step.

3

Publish the announcement to the channel

POST /messages/text

sendMessageText posts the prepared text to that channel. Put the channel id in to and the announcement in body.

Need delivery tracking? A successful API response does not mean every subscriber already received the post. Learn about delivery status →

Prerequisites

Before you run the flow

Connect the WhatsApp number that owns the channel, and authenticate every request with that number's API token. Publish hooks, CMS mapping, and which channel to target stay on your backend.

Optional — go deeper for this flow

API implementation

List the channel, then post

Read the channel JID from the newsletters list, then publish the announcement body to that id when your content event fires.

Get your API token for free after you register on whapi.cloud, and use that token in the code instead of Your_Token from the examples.

Resolve the target channel JID

Return channel metadata so the worker can pick the correct JID when it is not already stored in config.

curl --request GET \
     --url https://gate.whapi.cloud/newsletters \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/newsletters",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import requests

url = "https://gate.whapi.cloud/newsletters"

headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token",
}

response = requests.get(url, headers=headers)

print(response.text)
const url = 'https://gate.whapi.cloud/newsletters';

const response = await fetch(url, {
  method: 'GET',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
  },
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/newsletters")
  .get()
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/newsletters");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
var response = await client.GetAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://gate.whapi.cloud/newsletters", nil)
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}

Publish the announcement to the channel

Publish the prepared announcement text to that channel so subscribers see the update with a channel notification.

curl --request POST \
     --url https://gate.whapi.cloud/newsletters/link/{InviteCode} \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token' \
     --header 'content-type: application/json' \
     --data '
{
  "to": "1203632001928471@newsletter",
  "body": "New on the site: Summer promo is live. Read more: https://example.com/promo"
}
'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/newsletters/link/{InviteCode}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"to\":\"447123456789\"}",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token",
    "content-type: application/json"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import requests

url = "https://gate.whapi.cloud/newsletters/link/{InviteCode}"

payload = {
  "to": "1203632001928471@newsletter",
  "body": "New on the site: Summer promo is live. Read more: https://example.com/promo"
}
headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token",
    "content-type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const url = 'https://gate.whapi.cloud/newsletters/link/{InviteCode}';

const response = await fetch(url, {
  method: 'POST',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
    'content-type': 'application/json',
  },
  body: JSON.stringify({
  "to": "1203632001928471@newsletter",
  "body": "New on the site: Summer promo is live. Read more: https://example.com/promo"
}),
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"to\":\"447123456789\"}");
Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/newsletters/link/{InviteCode}")
  .post(body)
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .addHeader("content-type", "application/json")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/newsletters/link/{InviteCode}");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
request.AddHeader("content-type", "application/json");
request.AddJsonBody(new { to = "447123456789" });
var response = await client.PostAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	body := []byte(`{"to":"1203632001928471@newsletter","body":"New on the site: Summer promo is live. Read more: https://example.com/promo"}`)
	req, _ := http.NewRequest("POST", "https://gate.whapi.cloud/newsletters/link/{InviteCode}", bytes.NewReader(body))
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")
	req.Header.Set("content-type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
Delivery

Know when the post landed

A successful send response does not mean every subscriber already has the post. The first status visible before a webhook is pending. Later status changes arrive only on statuses.post and statuses.put. If the status stays pending and does not move to sent, delivered, or a later ack, the message was not delivered. Check the payload and the account's permission to send to that channel.

  • A response from sendMessageText is not proof every subscriber received the announcement.

  • pending that never moves on means the post was not delivered.

  • Watch statuses.post and statuses.put for later acks on channel sends.

  • Enable webhooks if your worker should retry when delivery never completes.

What to read on delivery and webhooks

Contact our support if something went wrong
When things break

Handle failures at each step

Content can go live on the site while the channel sync still breaks when the newsletters list is empty, the wrong channel JID is chosen, or sendMessageText is rejected or not delivered.

Site published, but the channel did not update?

Keep the CMS publish state separate from channel sync. If getNewsletters fails or returns no matching channel, or sendMessageText fails, retry or alert ops and do not mark the content as synced to the channel. If the channel post still fails after a retry, contact Whapi support with the channel id and the failed response.

Contact our support if something went wrong

Troubleshoot by API step

Status What it means What to do
400 Wrong request parameters Wrong request parameters — check count and offset on the list request.
500 Internal Error
Status What it means What to do
400 Wrong request parameters Wrong request parameters — check to and body on the send payload.
401 Need channel authorization for send message Need channel authorization for send message — confirm the connected number can post to that channel.
402 Trial version limit exceeded
403 It is forbidden to send to this group/recipient It is forbidden to send to this group/recipient — confirm the channel JID from the list step.
413 Request body too large
429 Too many requests
500 Internal Error
FAQ

Questions integrators ask

If the channel JID is already stored in your config, you can skip getNewsletters and call sendMessageText with that id. When the id is unknown or channels change, list first.
No. This flow posts to one WhatsApp Channel. Community-wide announcements through linked groups are a separate scenario.
No. This flow publishes once to a channel JID. Cold DMs to individual numbers are a different job.
Yes. Put the URL in body with your announcement text. A personal-chat link is one optional CTA when the channel has no in-post reply thread.
No. You compose the announcement in body and send it with sendMessageText. The send does not wait on a pre-approved template for that message.
If the list step fails, no channel matches, or the send fails, retry or alert ops and do not mark the content as synced to the channel until publish succeeds.
Supported WhatsApp Features

Everything you need to build WhatsApp automation

Whapi.Cloud gives you access to a complete set of WhatsApp features — messaging, media, groups, channels, webhooks and more. Build bots, automations and integrations without feature limitations.

Chosen by developers

Trusted by 3,300+ developers and SaaS teams

Developers worldwide rely on Whapi.Cloud to build automations, bots, CRM integrations, bulk messaging tools and advanced WhatsApp workflows. Our infrastructure processes millions of API requests with high stability — and grows every month.

Icon of feature

5,5K+

active API channels

Icon of feature

21M+

API requests processed monthly

“Everything is simple, intuitive and easy to navigate. The docs are clear, and all the info I need is right on the screen. Great job.”

roberto k. / Web Developer

“We connected WhatsApp to our workflows using n8n in just a few minutes. No code, no complications- everything worked on the first try.”

Martin p. / Developer

“Whapi.Cloud became a key part of our customer communication. We automated product updates, order notifications and support messages without needing Meta templates or approvals”

Oscar T. / CTO

Decorative bubble