On this page
POST/campaigns/:campaignId/leads/batch-update
Credits: None
LinkedIn risk: None
Purpose
Update tag, excluded, and/or CRM/profile fields for up to 100 leads in one call. Prefer this over many PATCH …/leads/:leadId calls.
CRM fields match the in-app editor (empty string clears). LinkedIn URL is not writable.
Exclude is workspace-global when a LinkedIn URL is available. If there is no LinkedIn URL, only the campaign lead’s excluded flag is set locally (same as single PATCH). Auto-exclude tags (Not interested, Wrong person) apply immediately (unlike some inbox flows).
Request
POST /campaigns/search_abc/leads/batch-update
X-API-Key: sk_live_...
Idempotency-Key: optional-key
Content-Type: application/json
{
"updates": [
{ "leadId": "lead_xyz", "excluded": true },
{ "leadId": "lead_abc", "tag": "Interested", "custom1": "Warm intro" }
]
}
| Field | Notes |
|---|---|
updates | Yes — non-empty array, length 1…maxItems (default/hard max 100) |
updates[].leadId | Required; lead_ prefix normalized |
updates[].tag | Optional; allowlisted labels or null to clear |
updates[].excluded | Optional boolean |
updates[].… | Optional CRM/profile strings (same keys as PATCH lead) |
At least one of tag / excluded / a CRM field per item. Unknown top-level keys → 400. Soft per-item: bad id, duplicate leadId (first wins), auto-exclude tag + excluded: false.
Idempotency: array order matters (fingerprint). Persist 200 only when summary.updated > 0.
Response 200
{
"results": [
{
"index": 0,
"leadId": "lead_xyz",
"status": "updated",
"tag": null,
"excluded": true
}
],
"summary": {
"total": 1,
"updated": 1,
"not_found": 0,
"validation_error": 0,
"failed": 0
},
"creditsCharged": 0
}
Statuses: updated · not_found · validation_error · failed. Optional fields object when CRM writes landed.
If the handler fails mid-batch after durable writes, response is still 200 with completed rows as updated (only fields that actually landed — e.g. a tagged auto-exclude row does not claim excluded: true until the bulk/local exclude step succeeds) and remaining as failed. Idempotency-Key is persisted when summary.updated > 0.
vs single PATCH
| Behavior | PATCH | Batch update |
|---|---|---|
| Auto-exclude timing | May defer in some inbox flows | Immediate |
| Global exclude (with LinkedIn URL) | Yes (per lead) | Yes (one bulk) |
| No LinkedIn URL + exclude | Lead flag only | Same (local mark) |
excluded: false | Lead flag only | Same |
| CRM/profile scalars | Yes | Yes |
lead.tagged webhook | 1 | Up to 100 |
MCP
Tool: update_leads_batch.