On this page

POST/campaigns/:campaignId/leads/batch-update

Update tag and/or excluded for up to 100 leads in one call. Prefer over many PATCH …/leads/:leadId calls.

0 credits. Rate class update_leads_batch (default 6/min). Max 100 items. Optional Idempotency-Key (max 128) — server persists a replay when summary.updated > 0.

Exclude is workspace-global when the lead has an email. Auto-exclude tags (Not interested, Wrong person) apply immediately (no polite-ack defer — differs from single PATCH / inbox).

Request

POST /campaigns/search-xyz/leads/batch-update
X-API-Key: sk_live_...
Content-Type: application/json
Idempotency-Key: client-unique-batch-update-1
{
  "updates": [
    { "leadId": "lead_abc", "excluded": true },
    { "leadId": "lead_def", "tag": "Interested" }
  ]
}
FieldRequiredNotes
updatesYesNon-empty array, length 1…100
updates[].leadIdYesNumeric ids normalize to lead_N
updates[].tagNoWritable allowlist (same as PATCH): Interested, Not interested, Wrong person, Meeting booked, Resolved; or null to clear
updates[].excludedNoboolean

At least one of tag / excluded per item. Unknown top-level keys → 400.

Soft per-item outcomes (not envelope errors):

  • Bad / unknown leadIdnot_found
  • Duplicate leadId in the same request → first wins; later copies → validation_error
  • Auto-exclude tag (Not interested / Wrong person) with excluded: falsevalidation_error

Idempotency: array order matters. Persist when summary.updated > 0 (including durable mid-batch partial success that still returns 200).

Response

{
  "results": [
    {
      "index": 0,
      "leadId": "lead_abc",
      "status": "updated",
      "tag": null,
      "excluded": true
    },
    {
      "index": 1,
      "leadId": "lead_def",
      "status": "updated",
      "tag": "Interested",
      "excluded": false
    }
  ],
  "summary": {
    "total": 2,
    "updated": 2,
    "not_found": 0,
    "validation_error": 0,
    "failed": 0
  },
  "creditsCharged": 0
}

Per-item status: updated | not_found | validation_error | failed.

If the handler fails mid-batch after durable writes, response is still 200 with completed rows as updated (only fields that actually landed — never infer excluded from an auto-exclude tag alone) and remaining as failed.

vs single PATCH

PATCHbatch-update
Auto-exclude deferPossibleNo — immediate
Global excludePer-leadOne coalesced workspace exclude
Rate~60/min6/min
Idempotency-KeyNoOptional

Errors

Error codeWhen
validation_errorEmpty/updates over max / unknown body keys / bad Idempotency-Key
not_foundUnknown campaign
conflictIdempotency mismatch / in progress
upstream_unavailableIdempotency store unavailable, or hard failure before any durable work

MCP

Tool: update_leads_batch (0 credits).