You have two ways to detect when customers connect their WhatsApp account through setup links.
1. Project webhooks
Configure a project webhook to receive the whatsapp.phone_number.created event. This is the recommended approach for server-to-server notifications.
Setup
- Open the sidebar and click Webhooks
- Go to the Project webhooks tab
- Click Add Webhook
- Enter your HTTPS endpoint URL
- Copy the auto-generated secret key
- Subscribe to
whatsapp.phone_number.created event
Webhook payload
{
"phone_number_id": "123456789012345",
"project": {
"id": "990e8400-e29b-41d4-a716-446655440004"
},
"customer": {
"id": "880e8400-e29b-41d4-a716-446655440003"
}
}
Handle the webhook
app.post('/webhooks/project', async (req, res) => {
const { event, data } = req.body;
if (event === 'whatsapp.phone_number.created') {
const { phone_number_id, customer } = data;
// Update your database
await db.customers.update(customer.id, {
phone_number_id,
whatsapp_connected: true,
connected_at: new Date()
});
// Trigger welcome flow
await sendWelcomeMessage(phone_number_id, customer.id);
}
res.status(200).send('OK');
});
See webhooks documentation for signature verification and best practices.
2. Success redirect URL
When customers complete WhatsApp setup, they’re redirected to your success_redirect_url with query parameters.
Setup
When creating a setup link, provide redirect URLs:
const setupLink = await fetch('https://api.kapso.ai/platform/v1/customers/customer-123/setup_links', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
setup_link: {
success_redirect_url: 'https://your-app.com/whatsapp/success',
failure_redirect_url: 'https://your-app.com/whatsapp/failed'
}
})
});
Query parameters
After successful setup, customer is redirected to:
https://your-app.com/whatsapp/success?setup_link_id=...&status=completed&phone_number_id=123456789012345&business_account_id=...&whatsapp_config_id=...&provisioned_phone_number_id=...&display_phone_number=%2B15551234567
Parameters:
setup_link_id - UUID of the setup link
status - Always completed for success
phone_number_id - WhatsApp phone number ID (primary identifier)
business_account_id - Meta WABA ID (if available)
whatsapp_config_id - Legacy identifier (still provided for backward compatibility)
provisioned_phone_number_id - Kapso phone number ID (if provisioning was used)
display_phone_number - E.164 formatted phone number (URL encoded)
Handle the redirect
app.get('/whatsapp/success', async (req, res) => {
const {
setup_link_id,
status,
phone_number_id,
business_account_id,
provisioned_phone_number_id,
display_phone_number,
whatsapp_config_id // Legacy support
} = req.query;
// Update your database
await db.customers.update({
phone_number_id,
business_account_id,
display_phone_number: decodeURIComponent(display_phone_number),
whatsapp_connected: true,
connected_at: new Date()
});
// Show success page to customer
res.render('whatsapp-connected', {
phoneNumber: decodeURIComponent(display_phone_number)
});
});
These parameters are convenience identifiers to avoid extra API fetches. Use phone_number_id as the primary identifier.
Failure redirect
If setup fails, customer is redirected to your failure_redirect_url:
https://your-app.com/whatsapp/failed?setup_link_id=...&error_code=facebook_auth_failed
Error codes:
facebook_auth_failed - Facebook login cancelled
phone_verification_failed - Phone verification failed
waba_limit_reached - Too many WhatsApp accounts
token_exchange_failed - OAuth failed
link_expired - Link expired (30 days)
already_used - Link already used
app.get('/whatsapp/failed', (req, res) => {
const { setup_link_id, error_code } = req.query;
// Log failure for monitoring
await logSetupFailure(setup_link_id, error_code);
// Show user-friendly error message
res.render('whatsapp-setup-failed', {
errorMessage: getErrorMessage(error_code)
});
});
Choosing the right method
Use project webhooks when:
- You need server-to-server notification
- Customer doesn’t need immediate visual feedback
- You’re building automated onboarding flows
- You need to process the connection before showing UI
Use success redirect when:
- Customer needs immediate confirmation in your app
- You want to show a custom success page
- You’re building a wizard-style onboarding flow
- You need to collect additional information after connection
Use both:
- Webhook for backend processing (database updates, welcome messages)
- Redirect for frontend experience (success page, next steps)