On this page

POST/campaigns/:campaignId/leads/batch

Insert up to 100 LinkedIn profiles into an existing campaign in one HTTP call. Same credit, dedupe, exclude, and occupancy rules as POST …/leads.

For CRM / n8n bulk push: chunk lists larger than 100 (e.g. 185 → 100 + 85). Clients must call this route — parallel single-lead POSTs still hit per-key RPM. Raising RPM alone does not fix bulk dumps.

Credits: 1 per successfully inserted lead (summed in creditsCharged).
Rate class: 10 / minute (still subject to the global 120 / minute per key).


Request

POST /campaigns/search_abc/leads/batch
X-API-Key: sk_live_...
Content-Type: application/json
Idempotency-Key: optional-uuid
{
  "leads": [
    {
      "linkedinUrl": "https://www.linkedin.com/in/jane-doe/",
      "fullName": "Jane Doe",
      "jobTitle": "VP Sales",
      "companyName": "Acme"
    }
  ]
}
FieldRequiredNotes
leadsYesNon-empty array, length 1…100 (hard max)
leads[]Same allowlist as single add-lead (linkedinUrl required; optional profile fields with the same length caps)
  • Top-level allowlist: only leads. Unknown keys → whole-request 400.
  • Per-item unknown keys / bad types / over-length → whole-request 400 (no inserts).
  • Invalid LinkedIn URL on one item → that index is validation_error in results; siblings still process.
  • Body subject to global 128 KiB cap — sparse CRM rows are fine; heavy personalization may need smaller chunks.

Response 200

Always 200 when the envelope is valid and the campaign exists:

{
  "results": [
    {
      "index": 0,
      "linkedinUrl": "https://www.linkedin.com/in/jane-doe/",
      "leadId": "lead_12",
      "status": "created",
      "creditsCharged": 1
    }
  ],
  "summary": {
    "total": 1,
    "created": 1,
    "duplicate": 0,
    "excluded": 0,
    "validation_error": 0,
    "insufficient_credits": 0,
    "failed": 0
  },
  "creditsCharged": 1
}
Per-item statusCredit
created1
duplicate / excluded / validation_error / insufficient_credits / failed0

On first credit exhaustion, that item and all remaining items are marked insufficient_credits without further inserts. Still HTTP 200.

Idempotency

Idempotency-Key is only stored when at least one item is created, duplicate, or excluded. All-insufficient / all-validation / all-failed batches release the key so top-up / fix-and-retry works. Fingerprint includes the full body (order matters).

Whole-request errors (not partial 200)

error.codeWhen
validation_errorBad envelope / types / unknown keys / over-length
not_foundCampaign missing before any insert
conflictIdempotency conflict
rate_limitedPer-key batch RPM or global RPM
upstream_unavailableIdempotency reserve fail — no inserts

MCP

Tool: add_leads_batch → same REST route. Optional idempotencyKey.

See also