Skip to content

Add an opt-in lead (sends their first message)

POST
/campaigns/{id}/leads
curl --request POST \
--url https://app.whatsetter.com/api/v1/campaigns/example/leads \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "phone": "+33612345678", "name": "Marie Dupont", "email": "marie@acme.fr", "source_url": "crm:hubspot", "additional_data": { "offre": "Pack Pro", "ville": "Lyon", "budget": "500-1000" } }'

The CRM primitive for opt-in leads: when someone signs up on your client’s funnel or CRM, push them here and WhatSetter runs the exact same pipeline as the campaign’s public sales-page webhook, with the anti-ban protections applied automatically:

  1. Phone validation and WhatsApp-registration check, deduplication against leads already contacted.
  2. Daily first-contact quota and anti-bot pacing: over-quota leads are queued for the next window, never dropped.
  3. The AI writes a personalized first message from the campaign’s template, the lead’s name, the source, and every key you pass in additional_data (budget, city, product of interest, plan…).
  4. The lead lands in the campaign and the agent handles replies.

The pipeline is asynchronous, so the endpoint answers 202 as soon as the lead is accepted. Follow progress with GET /leads (filter on campaign_id) or the signed webhooks. Accepts the campaign document id or its campaign_id slug in the path. Requires scope messages:send.

id
required
string

Campaign document id, or its campaign_id slug.

Media typeapplication/json
object
phone
required

International format, e.g. +33612345678.

string
name
string
<= 255 characters
email
string
<= 255 characters
source_url

Where the lead came from (defaults to api).

string
<= 255 characters
additional_data

Free-form CRM fields (up to 30 keys, 2000 characters total). The AI uses them to personalize the first message.

object
Example
{
"phone": "+33612345678",
"name": "Marie Dupont",
"email": "marie@acme.fr",
"source_url": "crm:hubspot",
"additional_data": {
"offre": "Pack Pro",
"ville": "Lyon",
"budget": "500-1000"
}
}

Lead accepted into the first-contact pipeline

Media typeapplication/json
object
data
object
status
string
campaign_id
string
phone
string
note
string
Example
{
"data": {
"status": "accepted"
}
}

Missing, unknown or revoked API key

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

The key lacks the required scope

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Resource not found in this workspace

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Campaign is not active

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Invalid parameter or body

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

First-message pipeline unreachable

Media typeapplication/json
object
error
object
code
string
message
string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}