docs(whatsapp): Update WhatsApp Business API setup guide
Some checks failed
CI / Test (1.22) (push) Failing after -24m48s
CI / Test (1.23) (push) Failing after -24m45s
CI / Build (push) Successful in -27m0s
CI / Lint (push) Successful in -26m50s

* Add registration process for new phone numbers
* Clarify importance of registration for sending messages and 2FA
* Improve formatting and clarity throughout the document
This commit is contained in:
Hein
2026-01-30 17:06:04 +02:00
parent c5e121de4a
commit 98fc28fc5f

View File

@@ -5,6 +5,7 @@ This guide will help you set up WhatsApp Business API credentials for use with W
## Common Error: "Object does not exist or missing permissions"
If you see this error:
```
Failed to connect client account_id=test error="API returned status 400:
{\"error\":{\"message\":\"Unsupported get request. Object with ID 'XXXXXXXXX' does not exist,
@@ -74,6 +75,7 @@ curl -X GET 'https://graph.facebook.com/v21.0/debug_token?input_token=YOUR_TOKEN
```
Look for `"scopes"` in the response - it should include:
```json
{
"data": {
@@ -106,6 +108,7 @@ curl -X GET 'https://graph.facebook.com/v21.0/YOUR_BUSINESS_ACCOUNT_ID/phone_num
```
Response:
```json
{
"data": [
@@ -128,13 +131,85 @@ curl -X GET 'https://graph.facebook.com/v21.0/me/businesses' \
```
Or find it in WhatsApp Manager:
1. Go to WhatsApp Manager
2. Click on **Settings** (gear icon)
3. The Business Account ID is shown in the URL: `https://business.facebook.com/wa/manage/home/?waba_id=XXXXXXXXX`
## Step 7: Test Your Credentials
## Step 7: Register Your Phone Number (Required for New Numbers)
Before configuring WhatsHooked, test your credentials:
If this is a new phone number that hasn't been used for WhatsApp Business API before, you need to register it first.
### Why Registration is Needed
Phone numbers must be registered with WhatsApp to:
- Activate the number for sending messages
- Set up two-factor authentication (2FA)
- Verify ownership of the phone number
### Registration Process
**1. Get your 2FA PIN:**
You should have received a 6-digit PIN when you set up your WhatsApp Business phone number. If you don't have it:
- Go to [WhatsApp Manager](https://business.facebook.com/wa/manage/home/)
- Select your phone number
- Go to **Settings****Two-step verification**
- Note or reset your PIN
**2. Register the phone number:**
```bash
# Replace PHONE_NUMBER_ID with your Phone Number ID
# Replace YOUR_TOKEN with your access token
# Replace 890523 with your actual 2FA PIN
curl -X POST 'https://graph.facebook.com/v21.0/PHONE_NUMBER_ID/register' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"messaging_product": "whatsapp",
"pin": "123123"
}'
```
**Successful Response:**
```json
{
"success": true
}
```
**Error Response (if already registered):**
```json
{
"error": {
"message": "(#131030) Phone number has already been registered",
"type": "OAuthException",
"code": 131030,
"fbtrace_id": "..."
}
}
```
**Note:** If you get error code 131030, it means your number is already registered and you can skip this step.
### Important Notes
- ⚠️ **You only need to register once** - don't repeat this step unless you're setting up a new number
- ⚠️ **Keep your PIN secure** - it's used for two-factor authentication
- ⚠️ **Registration can take a few minutes** - wait before sending messages
- ⚠️ **If registration fails**, verify:
- Your PIN is correct (6 digits)
- Your access token has `whatsapp_business_management` permission
- The phone number is verified in Meta Business Manager
## Step 8: Test Your Credentials
After registration, test your credentials to confirm everything is working:
```bash
# Replace PHONE_NUMBER_ID and YOUR_TOKEN
@@ -143,6 +218,7 @@ curl -X GET 'https://graph.facebook.com/v21.0/PHONE_NUMBER_ID' \
```
If successful, you'll get a response like:
```json
{
"verified_name": "Your Business Name",
@@ -154,7 +230,7 @@ If successful, you'll get a response like:
If you get an error like `"error_subcode":33`, your token lacks permissions - go back to Step 4.
## Step 8: Configure WhatsHooked
## Step 9: Configure WhatsHooked
Update your `config.json` with the Business API configuration:
@@ -180,7 +256,7 @@ Update your `config.json` with the Business API configuration:
### Configuration Fields
| Field | Required | Description |
|-------|----------|-------------|
| --------------------- | -------- | ------------------------------------------------------ |
| `id` | Yes | Unique identifier for this account in WhatsHooked |
| `type` | Yes | Must be `"business-api"` |
| `phone_number` | Yes | Your WhatsApp Business phone number (E.164 format) |
@@ -188,9 +264,9 @@ Update your `config.json` with the Business API configuration:
| `access_token` | Yes | Permanent access token (from Step 4) |
| `business_account_id` | No | WhatsApp Business Account ID (optional, for reference) |
| `api_version` | No | Graph API version (defaults to `"v21.0"`) |
| `verify_token` | Yes | Random string for webhook verification (see Step 8a) |
| `verify_token` | Yes | Random string for webhook verification (see Step 9a) |
### Step 8a: Generate Verify Token
### Step 9a: Generate Verify Token
The verify token is used by Meta to verify your webhook endpoint. Generate a secure random string:
@@ -202,33 +278,36 @@ openssl rand -hex 32
# "my_secure_verify_token_abc123xyz789"
```
Add this token to your `config.json` (see above) and save it - you'll need it for webhook configuration in Step 10.
Add this token to your `config.json` (see above) and save it - you'll need it for webhook configuration in Step 11.
## Step 9: Start WhatsHooked
## Step 10: Start WhatsHooked
```bash
./bin/whatshook-server -config config.json
```
You should see:
```
INFO Business API client connected account_id=business phone=+1234567890
INFO Hook manager started and subscribed to events event_types=13
```
If you see `Failed to connect client`, check the error message and verify:
1. Phone Number ID is correct
2. Access token has required permissions
3. Access token hasn't expired
4. Business Account has WhatsApp API access enabled
## Step 10: Configure Webhook in Meta Developer Console
## Step 11: Configure Webhook in Meta Developer Console
WhatsHooked provides a webhook endpoint to receive incoming messages and status updates from WhatsApp.
### 10.1: Webhook URL Format
### 11.1: Webhook URL Format
Your webhook URL should be:
```
https://your-domain.com/webhooks/whatsapp/{account_id}
```
@@ -236,11 +315,12 @@ https://your-domain.com/webhooks/whatsapp/{account_id}
Where `{account_id}` matches the `id` field in your config (e.g., "business").
**Example**: If your domain is `api.example.com` and account ID is `business`:
```
https://api.example.com/webhooks/whatsapp/business
```
### 10.2: Configure in Meta Developer Console
### 11.2: Configure in Meta Developer Console
1. Go to [Meta Developers](https://developers.facebook.com/)
2. Select your app
@@ -253,9 +333,10 @@ https://api.example.com/webhooks/whatsapp/business
Meta will send a GET request to verify your endpoint. If verification succeeds, you'll see a green checkmark.
### 10.3: Subscribe to Webhook Events
### 11.3: Subscribe to Webhook Events
After verification, subscribe to these webhook fields:
-**messages** - Incoming messages and message status updates
-**message_template_status_update** - Template approval/rejection (optional)
-**account_update** - Account changes (optional)
@@ -270,7 +351,7 @@ WhatsHooked supports all WhatsApp Business API webhook events and message types:
### Message Types
| Type | Supported | Downloads Media | Description |
|------|-----------|-----------------|-------------|
| ------------- | --------- | --------------- | --------------------------------- |
| `text` | ✅ | N/A | Text messages |
| `image` | ✅ | ✅ | Images with optional caption |
| `video` | ✅ | ✅ | Videos with optional caption |
@@ -288,7 +369,7 @@ WhatsHooked supports all WhatsApp Business API webhook events and message types:
### Status Updates
| Status | Event | Description |
|--------|-------|-------------|
| ----------- | ------------------- | ------------------------------ |
| `sent` | `message.sent` | Message sent from your number |
| `delivered` | `message.delivered` | Message delivered to recipient |
| `read` | `message.read` | Message read by recipient |
@@ -297,7 +378,7 @@ WhatsHooked supports all WhatsApp Business API webhook events and message types:
### Webhook Notification Types
| Field | Description | Events Published |
|-------|-------------|------------------|
| -------------------------------- | ---------------------- | ------------------------------------------ |
| `messages` | Message events | `message.received`, message status updates |
| `message_template_status_update` | Template changes | Logged to console |
| `account_update` | Account config changes | Logged to console |
@@ -382,9 +463,7 @@ DEBUG Sending to hook hook_id=message_hook url=https://your-webhook.com/messages
}
```
## Step 11: Configure Your Webhooks
## Step 11: Configure Your Webhooks
## Step 12: Configure Your Webhooks
WhatsHooked forwards events to your own webhook URLs. Configure them in `config.json`:
@@ -415,7 +494,7 @@ WhatsHooked forwards events to your own webhook URLs. Configure them in `config.
### Hook Configuration Fields
| Field | Required | Description |
|-------|----------|-------------|
| ------------- | -------- | ------------------------------------------- |
| `id` | Yes | Unique identifier for this hook |
| `name` | Yes | Human-readable name |
| `url` | Yes | Your webhook URL to receive events |
@@ -428,6 +507,7 @@ WhatsHooked forwards events to your own webhook URLs. Configure them in `config.
### Available Event Types
**Message Events:**
- `message.received` - Incoming messages
- `message.sent` - Outgoing messages
- `message.delivered` - Delivery confirmations
@@ -435,15 +515,18 @@ WhatsHooked forwards events to your own webhook URLs. Configure them in `config.
- `message.failed` - Delivery failures
**Connection Events:**
- `whatsapp.connected` - Account connected
- `whatsapp.disconnected` - Account disconnected
**QR Code Events** (whatsmeow only):
- `whatsapp.qr.code` - QR code for pairing
- `whatsapp.qr.timeout` - QR code expired
- `whatsapp.qr.error` - QR code error
**Hook Events:**
- `hook.triggered` - Hook was called
- `hook.success` - Hook responded successfully
- `hook.failed` - Hook call failed
@@ -481,6 +564,7 @@ Add to your `config.json`:
### When Events Are Cached
Events are automatically cached when:
- No webhooks are configured for the event type
- All webhooks are inactive (`"active": false`)
- No webhooks match the event in their `events` array
@@ -488,33 +572,39 @@ Events are automatically cached when:
### Cache Management API
**List cached events:**
```bash
curl -u username:password http://localhost:8080/api/cache
```
**Get cache statistics:**
```bash
curl -u username:password http://localhost:8080/api/cache/stats
```
**Replay all cached events:**
```bash
curl -X POST -u username:password http://localhost:8080/api/cache/replay
```
**Replay specific event:**
```bash
curl -X POST -u username:password \
"http://localhost:8080/api/cache/event/replay?id=EVENT_ID"
```
**Delete cached event:**
```bash
curl -X DELETE -u username:password \
"http://localhost:8080/api/cache/event/delete?id=EVENT_ID"
```
**Clear all cache:**
```bash
curl -X DELETE -u username:password \
"http://localhost:8080/api/cache/clear?confirm=true"
@@ -553,12 +643,14 @@ curl -X DELETE -u username:password \
**Error**: "The callback URL or verify token couldn't be validated"
**Causes**:
- `verify_token` mismatch between config.json and Meta console
- WhatsHooked server not running
- Firewall blocking Meta's IP ranges
- Wrong webhook URL format
**Fix**:
1. Ensure server is running: `./bin/whatshook-server -config config.json`
2. Check logs for verification attempt
3. Verify token matches exactly (case-sensitive)
@@ -567,6 +659,7 @@ curl -X DELETE -u username:password \
### Messages Not Cached
**Check**:
1. `message_cache.enabled` is `true` in config
2. Hooks are actually inactive or not matching events
3. Check cache stats: `curl -u user:pass http://localhost:8080/api/cache/stats`
@@ -574,11 +667,13 @@ curl -X DELETE -u username:password \
### No Hooks Configured Error
If events are being cached but you have hooks configured, check:
- Hook `"active"` is `true`
- Hook `"events"` array includes the event type (or is empty for all events)
- Hook URL is reachable and responding with 2xx status
Enable debug logging to trace the issue:
```json
{
"log_level": "debug"
@@ -726,10 +821,7 @@ Here's a complete `config.json` with all Business API features:
"url": "https://your-app.com/api/whatsapp/status",
"method": "POST",
"active": true,
"events": [
"whatsapp.connected",
"whatsapp.disconnected"
],
"events": ["whatsapp.connected", "whatsapp.disconnected"],
"description": "Monitors connection status"
}
],
@@ -761,6 +853,7 @@ Here's a complete `config.json` with all Business API features:
WhatsHooked supports three media delivery modes:
**1. Link Mode** (default, recommended)
```json
{
"media": {
@@ -769,11 +862,13 @@ WhatsHooked supports three media delivery modes:
}
}
```
- Downloads media and stores locally
- Webhooks receive URL: `https://your-domain.com/api/media/business/filename.jpg`
- Efficient for large media files
**2. Base64 Mode**
```json
{
"media": {
@@ -781,11 +876,13 @@ WhatsHooked supports three media delivery modes:
}
}
```
- Encodes media as base64 in webhook payload
- No separate download needed
- Good for small files, increases payload size
**3. Both Mode**
```json
{
"media": {
@@ -793,6 +890,7 @@ WhatsHooked supports three media delivery modes:
}
}
```
- Provides both URL and base64
- Maximum flexibility, largest payloads
@@ -820,6 +918,7 @@ Track all events to file and/or database:
```
Logged events include:
- All message events
- Connection status changes
- Hook success/failure
@@ -830,6 +929,7 @@ Logged events include:
Your webhooks can respond to trigger outgoing messages:
**Webhook Response Format:**
```json
{
"send_message": true,
@@ -866,11 +966,13 @@ Before going live:
### Error: "Object with ID does not exist" (error_subcode: 33)
**Cause**: One of the following:
- Incorrect Phone Number ID
- Access token lacks permissions
- Access token expired
**Fix**:
1. Verify token permissions (see Step 4)
2. Double-check Phone Number ID (see Step 5)
3. Generate a new token if needed
@@ -892,6 +994,7 @@ Before going live:
**Issue**: Using a User Access Token instead of System User token
**Fix**:
- Use a System User (Step 2) for permanent tokens
- User Access Tokens expire in 60 days
- System User tokens can be set to "Never expire"