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" }
]
}
| Field | Required | Max | Notes |
|---|---|---|---|
leads | Yes | 100 items | Top-level allowlist: only leads |
leads[].email | Yes | 254 | Soft invalid → per-item validation_error |
leads[].fullName | No | 120 | |
leads[].companyName | No | 200 | |
leads[].website | No | 500 |
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 code | When |
|---|---|
validation_error | Empty/leads over max / unknown body keys / bad Idempotency-Key |
not_found | Unknown campaign |
conflict | Idempotency mismatch / in progress |
upstream_unavailable | Idempotency 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).
Related
- Single add: POST …/leads
- Credits & rate limits: Credits and rate limits
MCP
Tool: add_leads_batch.