Onboard your customers' WhatsApp numbers
Send each of your customers a setup link that connects their WhatsApp number into their namespace, then react to the connection in a webhook.
If you run a platform with a namespace per customer, your customers
need to connect their own WhatsApp numbers without a Samva account. A setup link does that: you
create one for a namespace, send its URL to your customer, and they connect their number on a
Samva-hosted page through Meta's signup window. The number lands in the link's namespace, and Samva
sends you a whatsapp.number.connected webhook event that carries the metadata you attached to the
link, so you know which customer connected.
Create a link
Create the link with a key that can manage WhatsApp accounts. A key confined to a namespace creates links only for that namespace.
curl -X POST https://api.samva.dev/v1/whatsapp/setup-links \
-H "X-API-Key: samva_sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"namespaceId": "ns_3xk9mvt4znw8rh7q",
"redirectUrl": "https://platform.example.com/settings/whatsapp",
"metadata": { "customerId": "cus_123" }
}'samva whatsapp setup-links create --namespace ns_3xk9mvt4znw8rh7q \
--redirect-url https://platform.example.com/settings/whatsapp \
--metadata customerId=cus_123You can also create one from the Setup links section of the dashboard WhatsApp page.
| Field | Meaning |
|---|---|
namespaceId | The namespace the connected number joins. |
redirectUrl | Optional. Where the hosted page sends your customer after their number connects. An absolute https URL. |
metadata | Optional. Your own string labels, such as your customer's id. Returned on the link and on the whatsapp.number.connected event. |
expiresAt | Optional. When the link stops working. It defaults to 7 days ahead and can be at most 30 days ahead. |
Metadata holds at most 50 keys, with keys up to 64 characters and values up to 512 characters.
The response is the link plus its url:
{
"id": "wasl_8h2kq9vt4znw3rm7",
"namespaceId": "ns_3xk9mvt4znw8rh7q",
"status": "pending",
"redirectUrl": "https://platform.example.com/settings/whatsapp",
"metadata": { "customerId": "cus_123" },
"expiresAt": "2026-10-24T10:30:00.000Z",
"businessAccountId": null,
"completedAt": null,
"revokedAt": null,
"createdAt": "2026-10-17T10:30:00.000Z",
"updatedAt": "2026-10-17T10:30:00.000Z",
"url": "https://samva.dev/connect/whatsapp#token=..."
}The url is the link's credential and appears only in this response. Samva keeps a digest of it,
so it cannot show it again. If you lose it, revoke the link and create another.
Send it to your customer
Send the url to your customer through your own channel: your onboarding email, your app, or a
message from your team. Your customer opens it, signs in with Meta, and chooses or creates their
WhatsApp Business Account and phone number. They need no Samva account. A link connects one number
and then stops working.
When the number connects, Samva stores it in the link's namespace, as if it had been connected from
the dashboard, and sends your customer to redirectUrl when you set one.
The link acts on behalf of the team member who created it. If that member leaves your organization, their links stop working; create new ones from a current member.
A link that was used, revoked, or has expired answers your customer with a page saying so, and the
API reports it as 410. A new number connects as pending until Samva registers it with Meta; see
Status, quality, and limits.
Receive the connection
Every number that connects sends a whatsapp.number.connected event, whether it connected from the
dashboard or through a setup link. The event catalog describes
delivery and signing. An endpoint filtered to a namespace receives the event for its own namespace.
{
"type": "whatsapp.number.connected",
"timestamp": "2026-10-17T11:02:41.318Z",
"data": {
"organizationId": "org_5nq7vt3xkm2w9h4r",
"namespaceId": "ns_3xk9mvt4znw8rh7q",
"businessAccountId": "waba_7vt4znw8rh3xk9mq",
"phoneNumber": "+16175550123",
"phoneNumberId": "109876543210987",
"whatsappBusinessAccountId": "100123456789012",
"displayName": "Acme Salon",
"verificationStatus": "pending",
"reconnected": false,
"setupLink": {
"id": "wasl_8h2kq9vt4znw3rm7",
"metadata": { "customerId": "cus_123" }
}
}
}| Field | Meaning |
|---|---|
namespaceId | The namespace the number joined, or null for a number connected at organization level. |
businessAccountId | The Samva id of the connected account; use it with /v1/whatsapp/business-accounts. |
phoneNumberId, whatsappBusinessAccountId | Meta's ids for the number and its WhatsApp Business Account. |
verificationStatus | The account's status when the number connected. A new number is pending until Samva registers it. |
reconnected | true when the number was already connected and this signup renewed access to it. |
setupLink | The link the number connected through, with its id and your metadata; null when it connected from the dashboard. |
Match setupLink.metadata to your own customer record, then mark that customer connected. Handle
the event idempotently; deliveries can repeat.
Manage links
| Action | REST | CLI |
|---|---|---|
| List | GET /v1/whatsapp/setup-links | samva whatsapp setup-links list |
| Get | GET /v1/whatsapp/setup-links/{linkId} | samva whatsapp setup-links get <id> |
| Revoke | POST /v1/whatsapp/setup-links/{linkId}/revoke | samva whatsapp setup-links revoke <id> |
List accepts namespaceId and status, and pages by cursor. A link's status is one of:
| Status | Meaning |
|---|---|
pending | The link can still connect a number. |
completed | A number connected through it; businessAccountId names the account. |
revoked | You revoked it before it was used. |
expired | It passed expiresAt unused. |
Revoke a pending link when you sent it to the wrong person or no longer need it. Revoking a link
that is already completed, revoked, or expired answers 410. A key confined to a namespace lists,
reads, and revokes only that namespace's links.