Skip to content

WhatsApp Cloud — Manual Connection with a System User

How to connect a WhatsApp Cloud (Meta) number to ConnectGain manually, using a Meta System User token instead of the Facebook login wizard.

Use this guide when the number you want does not appear in the "Connect with Facebook" selector / Embedded Signup flow.


1. When to use this (vs. the Facebook wizard)

ConnectGain has two ways to connect a WhatsApp Cloud number, and they use two different Meta identities:

Flow Identity used Sees only…
Connect with Facebook (wizard / Embedded Signup) the person who logs in WABAs that person administers and grants on the consent screen
Manual Entry (this guide) a System User token you paste WABAs assigned to that system user

A number is missing from the wizard whenever the human logging in is not an admin of the WABA's owning business — most commonly a partner/client WABA that was assigned to a system user for server-to-server use, but never assigned to any person. The wizard can only show what the logged-in human can see; the system user, on the other hand, has the WABA assigned, so Manual Entry is the path.

Rule of thumb: if the WABA was set up for API/server use, it's a system-user WABA → connect it manually.


2. The three pieces you need

A WhatsApp Cloud connection is not one object — it's three:

Piece What it is Where to get it
Access Token the System User token (the actor that calls Meta) Business Settings → Users → System Users → Generate token
Phone Number ID the number under the WABA (not the phone number itself) App Dashboard → WhatsApp → API Setup
WABA ID the WhatsApp Business Account asset App Dashboard → WhatsApp → API Setup ("WhatsApp Business Account ID")

You authenticate as the system user, but you connect to a WABA. The system-user ID never goes into the form — the WABA ID and Phone Number ID do.

A 100059…-style ID is a user / system-user profile, not a WABA. WABA IDs look like 995632549547163. Don't paste a system-user ID into the WABA field.


3. Prerequisites in Meta Business Manager

Do these once, in business.facebook.com → Business Settings of the business that owns the WABA:

  1. Assign the WABA to the system user
  2. Users → System Users → select (or create) the system user.
  3. Add Assets → WhatsApp Accounts → select the WABA → enable Manage / Full control → Save.
  4. If there are multiple system users with the same name, match by ID, not name.

  5. Generate a permanent token

  6. On that system user, Generate New Token → select the ConnectGain/Appgain appToken expiration: Never.
  7. Tick scopes: whatsapp_business_management and whatsapp_business_messaging.
  8. Copy the token — this is your Access Token. (A system-user token never expires, which is why it's preferred over a short-lived login token.)

Confirm the token can actually reach the number before wiring it in. Replace <TOKEN>, <PHONE_NUMBER_ID>, <WABA_ID> (Graph API v22.0):

# (a) The token acts AS the right system user
curl "https://graph.facebook.com/v22.0/me?fields=id,name&access_token=<TOKEN>"

# (b) The number is reachable and live → expect status: CONNECTED
curl "https://graph.facebook.com/v22.0/<PHONE_NUMBER_ID>?fields=display_phone_number,verified_name,status,account_mode&access_token=<TOKEN>"

# (c) The WABA is approved & the business is verified
curl "https://graph.facebook.com/v22.0/<WABA_ID>?fields=name,account_review_status,business_verification_status&access_token=<TOKEN>"

If (b) returns Object … does not exist, cannot be loaded due to missing permissions (code 100 / subcode 33), the WABA is not assigned to this system user — go back to step 3.1.


5. Connect in ConnectGain

  1. Go to Settings → Channels and click Add Channel (opens the "Add New Channel" page).
  2. Select WhatsApp Cloud.
  3. Choose connection mode Manual Entry, then provider Meta.
  4. Fill in:
Field Value
Access Token the system user token from step 3.2
Phone Number ID from App Dashboard → WhatsApp → API Setup
WABA ID from App Dashboard → WhatsApp → API Setup
Verify Token any string you invent (e.g. cg_<name>_<random>) — see step 6
Confirm Account Password your ConnectGain login password (used once to provision channel credentials)
  1. Save.

What happens on save (identical to the Facebook wizard's Appgain calls): - Provisions a new Appgain suit → { suitId, apiKey }. - Configures the Meta vendor on the suit: PUT https://notify.appgain.io/{suitId}/config with vendor: "meta" and connection_info: { type, phone_number_id, waba_id, access_token }. - Inserts the channel (with waba_id persisted). - Syncs the same token to Appgain as the FBSessionToken so Appgain can act on behalf of the number.

The Access Token is also used as the Facebook session token — they are the same value, so there is no separate "Facebook Session Token" field.


6. Configure the webhook on Meta (so inbound + delivery status work)

In App Dashboard → WhatsApp → Configuration → Webhook: - Verify token: the exact same string you typed in the form. - Callback URL: your ConnectGain WhatsApp Cloud webhook endpoint. - Subscribe to the messages field.

The Verify Token is not something you fetch from Meta — it's a shared secret you choose, entered in both places so Meta's verification handshake matches.

Without the webhook, messages can still be sent, but you will not receive inbound messages or delivery/read/failed status callbacks.


7. Send a test message

WhatsApp requires an approved template to open a conversation (outside the customer's 24-hour service window). Supply a value for every template variable:

curl -X POST "https://graph.facebook.com/v22.0/<PHONE_NUMBER_ID>/messages" \
 -H "Authorization: Bearer <TOKEN>" \
 -H "Content-Type: application/json" \
 -d '{
 "messaging_product": "whatsapp",
 "to": "<RECIPIENT_E164_NO_PLUS>",
 "type": "template",
 "template": {
 "name": "<template_name>",
 "language": { "code": "<lang_code>" },
 "components": [
 { "type": "body", "parameters": [
 { "type": "text", "text": "Value1" },
 { "type": "text", "text": "Value2" }
 ] }
 ]
 }
 }'

A messages[].message_status: "accepted" response means Meta queued the message. Final delivered / read / failed status arrives only via the webhook (step 6).

To find a template's exact language and how many variables it expects:

curl "https://graph.facebook.com/v22.0/<WABA_ID>/message_templates?name=<template_name>&fields=name,status,category,language,components&access_token=<TOKEN>"

8. Troubleshooting

Symptom Cause Fix
Number not listed in the Facebook wizard The WABA is assigned to a system user, not the human logging in Use Manual Entry (this guide), or assign the WABA to your person in Business Settings
code 100 / subcode 33 "does not exist / missing permissions" on the WABA or number Token's identity has no access to that WABA Assign the WABA to the system user (step 3.1)
Token's /me returns the wrong system user Two system users (often same name) — token generated from the wrong one Generate the token from the system user that has the WABA assigned; match by ID
(#100) nonexisting field (phone_numbers) on an ID That ID is not a WABA (e.g. a Page or system-user profile) Use the real WABA ID from API Setup
(#132000) Number of parameters does not match Template has body variables you didn't fill Add a body component with one parameters entry per {{n}}
Send is accepted but not delivered No webhook capturing status; or the number's display name is PENDING_REVIEW (can_send_message: LIMITED); or recipient undeliverable (131026) Configure the webhook (step 6) to see the real status; wait for display-name approval to raise limits; confirm the recipient is on WhatsApp


Last updated: 2026-06-08.