On this page

POST/campaigns/:campaignId/leads/batch

Bulk manual lead insert by email. Prefer over parallel single POSTs when pushing many emails; chunk larger lists (max 100 per call).

1 credit per item with status: "created"; top-level creditsCharged is the sum. Optional Idempotency-Key (max 128) — the server persists the replay only if any item is created | duplicate | excluded (same idea as single add keeping a 200). Rate class: add_leads_batch (default 10/min).

When the request is accepted, responses are usually HTTP 200 with partial per-item outcomes. A hard failure before any durable insert (or idempotency-store failure) can return envelope 503 upstream_unavailable.

Request

POST /campaigns/search-xyz/leads/batch
X-API-Key: sk_live_...
Content-Type: application/json
Idempotency-Key: demo-batch-1
{
  "leads": [
    { "email": "jane@acme.com", "fullName": "Jane Doe" },
    { "email": "not-valid" },
    { "email": "bob@acme.com" }
  ]
}
FieldRequiredMaxNotes
leadsYes100 itemsTop-level allowlist: only leads
leads[].emailYes254Soft invalid → per-item validation_error
leads[].fullNameNo120
leads[].companyNameNo200
leads[].websiteNo500

Response

{
  "results": [
    { "index": 0, "email": "jane@acme.com", "leadId": "lead_1", "status": "created", "creditsCharged": 1 },
    { "index": 1, "email": "not-valid", "leadId": null, "status": "validation_error", "creditsCharged": 0, "error": { "code": "validation_error", "message": "email format is invalid." } },
    { "index": 2, "email": "bob@acme.com", "leadId": "lead_2", "status": "created", "creditsCharged": 1 }
  ],
  "summary": {
    "total": 3,
    "created": 2,
    "duplicate": 0,
    "excluded": 0,
    "validation_error": 1,
    "insufficient_credits": 0,
    "failed": 0
  },
  "creditsCharged": 2
}

Per-item status: created | duplicate | excluded | validation_error | insufficient_credits | failed. Soft failures may include optional error: { code, message }. Per-item email / leadId may be null on soft failures.

First insufficient_credits stops further core inserts; later processable items become insufficient_credits, while soft email failures stay validation_error.

When some items already succeeded and a later hard failure occurs, the response is still HTTP 200 with those rows marked failed.

Errors

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

Unlike single add, mid-batch credit exhaustion returns HTTP 200 with per-item insufficient_credits (not envelope 403). Envelope 503 applies only when nothing durable was inserted (or the idempotency store is down).

MCP

Tool: add_leads_batch.