Common workflows
Connect WhatsApp
Send your customer to PaalChat's hosted Meta signup and know when they are connected.
In a nutshell
Ask for a one-time connect link, redirect the customer's admin to it, and wait for the whatsapp.connection callback. PaalChat runs Meta's Embedded Signup, verifies everything with Meta and keeps the credentials.
How it works
- You ask for a link.
POST /businesses/{external_id}/whatsapp/connectreturns a one-time URL. - The admin opens it. On PaalChat's page they log in to Meta in Meta's own window, choose or create the WhatsApp Business account and phone number, and approve access.
- PaalChat verifies with Meta. It checks the grant, reads the account and its numbers, registers the number, subscribes webhooks and syncs templates.
- You are told. A
whatsapp.connectioncallback withevent: connectedarrives, and the admin can follow the link back to your app.
Your product never sees the Meta login or the Meta token.
1. Create the link
curl -X POST https://whatsapp.paaltech.org/api/v1/businesses/presec/whatsapp/connect \
-H "Authorization: Bearer $PAALCHAT_TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"return_url": "https://presec.skuuls.paaltech.org/settings/whatsapp"}'
public function connect()
{
$link = Http::withToken(config('services.paalchat.token'))->acceptJson()
->post('https://whatsapp.paaltech.org/api/v1/businesses/'.tenant('id').'/whatsapp/connect', [
'return_url' => route('settings.whatsapp'),
])->throw()->json('data');
return redirect()->away($link['url']);
}
app.post('/settings/whatsapp/connect', async (req, res) => {
const r = await fetch(`${BASE}/businesses/${req.shop.id}/whatsapp/connect`, {
method: 'POST', headers: HEADERS,
body: JSON.stringify({ return_url: 'https://pos.example.com/settings/whatsapp' }),
});
const { data } = await r.json();
res.redirect(data.url);
});
link = requests.post(f"{BASE}/businesses/{shop.id}/whatsapp/connect", headers=HEADERS,
json={"return_url": "https://pos.example.com/settings/whatsapp"}).json()["data"]
return redirect(link["url"])
{"data": {"url": "https://whatsapp.paaltech.org/connect/EsCRzWiltOSLzMBAvEyNHt4bdoWsdAYXwkPKiL2KT83aQk98NFn5coKqweclo4Ih", "expires_at": "2026-10-03T18:54:28+00:00"}}
Warning
Treat the link as a secret: whoever holds it can connect a WhatsApp account to this business. Send it only to the customer's administrator, and do not store it.
Link rules
- Valid for 72 hours and until it is used successfully. If the admin closes Meta's window, they can try again with the same link.
- Asking for a new link cancels older unused links for that business.
return_urlmust behttps://and on your product's registered return origins - ask PaalTech to register them (for examplehttps://*.skuuls.paaltech.orgfor every school subdomain). Any other URL gets422 return_url_not_allowed, so the connect page can never send your customers somewhere else. After success the page offers a link back to it withwhatsapp=connectedadded to the query.- A suspended business gets
409 business_suspended.
2. Wait for the result
The whatsapp.connection callback may arrive before or after the admin returns.
When they land on your return_url, read the state:
GET /api/v1/businesses/presec/whatsapp
{"data": {"status": "connected", "wabas": [{"waba_id": "102290129340398", "status": "connected",
"phone_numbers": [{"phone_number_id": "106540352242922", "display_phone_number": "+233 30 200 0000", "verified_name": "Presec Legon"}]}]}}
Show the number and verified name on your settings page.
Note
The business pays Meta for conversations directly. Remind the admin to add a payment method for the number in Meta's WhatsApp Manager.
If setup fails
If a step fails at Meta, the WhatsApp account goes back to pending (you get a
whatsapp.connection callback with event: setup_failed) and health.last_error
says why, in Meta's words. The same link still works, so the admin can simply try
again. Reconnecting the same account updates it in place - history and messages are kept.
Connection states
| State | Meaning | Can send? | What to do |
|---|---|---|---|
pending |
Not set up yet, or setup failed (health.last_error says why) |
No | Offer a new link |
connecting |
Signup finished, setup at Meta in progress | No | Wait |
connected |
Ready | Yes | - |
degraded |
Working, with a warning - usually the access token expires within 7 days | Yes | Ask the admin to reconnect soon |
maintenance |
Paused by PaalChat operators; sends get 409 connection_paused |
No | Retry later; incoming messages still arrive |
suspended |
Meta disabled the account | No | The business resolves it with Meta; it comes back by itself |
revoked |
The credential stopped working, or the customer removed PaalChat's access in Meta | No | Offer a new link |
disconnected |
Disconnected on purpose, by you or an operator | No | Offer a new link if they want it back |
Disconnect
When a customer leaves, disconnect each of their WhatsApp accounts:
DELETE /api/v1/businesses/presec/whatsapp/wabas/102290129340398
PaalChat deletes its Meta token and stops sending. The number stays the customer's at Meta.
Moving an account to another business
A WhatsApp account can move between two businesses on PaalChat (for example when a school's campuses merge). PaalTech requests the move; each business approves or rejects it through its product (List account transfers, Approve or reject a transfer); after both approve it moves 24 hours later, with its numbers and templates. Messages and conversations stay with the business they happened in.