Skip to main content
Setup links let customers connect their WhatsApp Business accounts to your platform. Send a link, customer clicks, logs in with Facebook, and you’re connected.

Quick start

Create a basic setup link:
curl -X POST https://api.kapso.ai/platform/v1/customers/{customer_id}/setup_links \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "setup_link": {
      "success_redirect_url": "https://your-app.com/whatsapp/success",
      "failure_redirect_url": "https://your-app.com/whatsapp/failed"
    }
  }'
Response includes a url you send to your customer. Links expire after 30 days. See Connection detection for handling successful connections.
Do not choose Display name only inside Meta embedded signup. That option can create a WhatsApp profile with a generic, limited Meta-managed number, commonly a +1 555... number, instead of the intended setup-link number. For Kapso onboarding, use the connection type selected in the setup link: Dedicated for API-only numbers or Coexistence for WhatsApp Business App pairing.
If you choose Display name only, treat the connection as misconfigured. You may have connected a limited Meta-managed number rather than the production WhatsApp number. These numbers can stop working after about 5 messages until Meta approves the display name, and display-name approval can be slow or deferred. You may need to delete or disconnect that profile and restart from a new setup link.

Connection types

Customers can connect their WhatsApp in two ways: Coexistence - Keep using WhatsApp Business app alongside API
  • 5 messages/second
  • App stays active
  • Good for small businesses
Dedicated - API-only access for automation
  • Up to 1000 messages/second
  • No app access
  • Built for scale

Redirect URLs

Configure where customers land after completing or failing setup:
{
  "setup_link": {
    "success_redirect_url": "https://your-app.com/whatsapp/success",
    "failure_redirect_url": "https://your-app.com/whatsapp/failed"
  }
}
Both URLs receive query parameters with setup details. See Connection detection for handling redirects and available parameters.

Connection type control

Show both options (default)

{
  "setup_link": {
    "allowed_connection_types": ["coexistence", "dedicated"]
  }
}

Coexistence only

For customers using WhatsApp Business app:
{
  "setup_link": {
    "allowed_connection_types": ["coexistence"]
  }
}

Dedicated only

For API-only automation:
{
  "setup_link": {
    "allowed_connection_types": ["dedicated"]
  }
}
When you provide one option, it auto-selects.

Theme customization

Match your brand colors:
{
  "setup_link": {
    "theme_config": {
      "primary_color": "#3b82f6",
      "background_color": "#ffffff",
      "text_color": "#1f2937",
      "muted_text_color": "#64748b",
      "card_color": "#f9fafb",
      "border_color": "#e5e7eb"
    }
  }
}
All colors use hex format (#RRGGBB).

Phone number provisioning

Automatically provision a phone number for customers:
{
  "setup_link": {
    "provision_phone_number": true,
    "phone_number_country_isos": ["US"]
  }
}

Country support

  • Default Kapso provisioning: ["US"]. See Instant setup
  • For your own Twilio account, multi-country support, and project-owned pre-verified pools, see Bring your own Twilio
{
  "setup_link": {
    "provision_phone_number": true,
    "phone_number_country_isos": ["US", "CL"]
  }
}
If the requested country has a ready project pool, setup can use a pre-verified number. If that country has no pool, or the pool is empty, the setup link still works and falls back to live provisioning. When provision_phone_number is enabled, complete Meta’s phone-number step with the Kapso-provided, BSP-provided, or project-pool number shown by the flow. Do not choose Display name only because the connected number may be a generic, limited Meta-managed number rather than the provisioned number.

Reconnect existing numbers

When a customer’s WhatsApp connection breaks (token revoked, Meta de-auth, password change), generate a setup link scoped to a specific phone number they already have on Kapso:
{
  "setup_link": {
    "reconnect_phone_number": "+14155551234"
  }
}
Kapso looks up the customer’s existing WhatsApp config matching that number, then forces the setup flow to refresh credentials for the same WABA + phone number. Behavior:
  • The number must already exist on a production WhatsApp config for this customer.
  • provision_phone_number is forced to false. Passing true returns 422.
  • allowed_connection_types is locked to ["dedicated"] or ["coexistence"] to match the existing config. Passing a different value returns 422.
  • During Meta’s embedded signup, the phone number selector is constrained to the matching number — if the customer connects a different account or number, setup fails.
If no config matches, the API returns 422 with reconnect_phone_number must match an existing WhatsApp config for this customer. If multiple configs match the same display number, the API returns 422 and you’ll need to resolve the duplicates first.

Full example

const setupLink = await fetch(
  `https://api.kapso.ai/platform/v1/customers/${customerId}/setup_links`,
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      setup_link: {
        success_redirect_url: 'https://app.example.com/onboarding/complete',
        failure_redirect_url: 'https://app.example.com/onboarding/error',
        allowed_connection_types: ['dedicated'],
        provision_phone_number: true,
        phone_number_country_isos: ['US'],
        theme_config: {
          primary_color: '#10b981',
          background_color: '#ffffff',
          text_color: '#111827'
        }
      }
    })
  }
);

// Send link to customer
await sendEmail(customer.email, {
  subject: 'Connect your WhatsApp',
  body: `Click here to connect: ${setupLink.data.url}`
});
curl https://api.kapso.ai/platform/v1/customers/{customer_id}/setup_links \
  -H "X-API-Key: YOUR_API_KEY"

Automatic revocation

Creating a new link revokes the previous one. Only one active link per customer.

Expiration

Links expire after 30 days. Check the expires_at field.