Update campaign lead
Update a campaign lead's status or AI tag. Status can only be changed to "active" or "paused".
When aiTag is set, a lead.tag_changed webhook is triggered if the tag value actually changed.
The aiTag must match an existing tag name in the workspace's AI tagging labels.
Subsequence enrollment / exit: when the new aiTag matches a subsequence
whose trigger.type='ai_tag' and trigger.value equals the tag (case-insensitive):
- Lead has no subsequence → enrolled in the matching one and any pending main-sequence send is canceled.
- Lead is already in the matching subsequence → no-op.
- Lead is in a different subsequence with no emails sent from it → switched into the matching subsequence (state reset).
- Lead is in a different subsequence with at least one email already sent → no switch (action
skippedInProgress); tag still updates.
When the new tag matches NO subsequence:
- Lead has no subsequence → no-op.
- Lead is in a subsequence with no emails sent from it → exits cleanly (
subsequence.status: 'completed',subsequence.completedAtset, leadstatus: 'completed', scheduling cleared;subsequence.idpreserved as a historical pointer). - Lead is in a subsequence with at least one email already sent → kept in (action
skippedInProgress); tag still updates.
When enrollment, switch, exit, or skip occurs, the response includes a
subsequenceEnrollment: { action, subsequenceName } field where action
is one of enrolled, switched, exited, skippedInProgress. If no
enrollment change happens, the field is omitted.
curl -X PATCH "https://api.sendkit.ai/v1/campaigns/example_string/leads/example_string" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"status": "paused",
"aiTag": "Interested"
}'
import requests
import json
url = "https://api.sendkit.ai/v1/campaigns/example_string/leads/example_string"
headers = {
"Content-Type": "application/json",
"X-Api-Key": "YOUR_API_KEY"
}
data = {
"status": "paused",
"aiTag": "Interested"
}
response = requests.patch(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://api.sendkit.ai/v1/campaigns/example_string/leads/example_string", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"X-Api-Key": "YOUR_API_KEY"
},
body: JSON.stringify({
"status": "paused",
"aiTag": "Interested"
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"status": "paused",
"aiTag": "Interested"
}`)
req, err := http.NewRequest("PATCH", "https://api.sendkit.ai/v1/campaigns/example_string/leads/example_string", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", "YOUR_API_KEY")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://api.sendkit.ai/v1/campaigns/example_string/leads/example_string')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(uri)
request['Content-Type'] = 'application/json'
request['X-Api-Key'] = 'YOUR_API_KEY'
request.body = '{
"status": "paused",
"aiTag": "Interested"
}'
response = http.request(request)
puts response.body
{
"success": true,
"data": {
"_id": "666a1b2c3d4e5f6a7b8c9d01",
"campaignId": "665a1b2c3d4e5f6a7b8c9d0e",
"status": "paused",
"aiTag": "Interested",
"currentSequenceStep": 1,
"replied": false,
"addedAt": "2025-06-15T09:00:00.000Z"
},
"subsequenceEnrollment": {
"action": "enrolled",
"subsequenceName": "Interested follow-up"
}
}
{
"success": false,
"error": {
"code": "INVALID_TAG",
"message": "Tag "InvalidTag" does not exist in workspace"
}
}
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Campaign lead not found"
}
}
/v1/campaigns/{campaignId}/leads/{campaignLeadId}Platform API key (sk_user_...) or Workspace API key (sk_...)
Campaign ID
Campaign lead record ID (the _id from the CampaignLead document, not the Lead ID)
The media type of the request body
New status for the campaign lead
AI tag for the campaign lead. Must match an existing workspace tag name. Set to null to clear.
Request Preview
Response
Response will appear here after sending the request
Authentication
API Key for authentication. Platform API key (sk_user_...) or Workspace API key (sk_...)
Path Parameters
Campaign ID
Campaign lead record ID (the _id from the CampaignLead document, not the Lead ID)
Body
AI tag for the campaign lead. Must match an existing workspace tag name. Set to null to clear.
Responses
pendingactivepausedcompletedbouncedunsubscribedrepliedremovedPresent only when the tag change triggered enrollment, switching, exit, or an in-progress skip.
enrolledswitchedexitedskippedInProgressInvalid tag
Campaign lead not found
Last updated today
Built with Documentation.AI