---
title: "Add leads"
method: POST
path: "/v1/campaigns/{cid}/leads"
tags: ["Leads"]
---

# Add leads

`POST /v1/campaigns/{cid}/leads`

## Request

- Base URL: `https://api.mailbeast.ai`
- URL: `https://api.mailbeast.ai/v1/campaigns/{cid}/leads`
- Auth: HTTP bearer

Add 1-100 leads to a campaign. Each is deduplicated by email within the campaign and provider-detected. The response summarizes the outcome and returns the created leads.

Requires one of the following scopes: `leads:write`, `leads:all`, `all:all`.

## Path parameters

- `cid` string, uuid, required

## Headers

- `Idempotency-Key` string

## Request body

- AddLeadsApiDto
  - `leads` LeadInputApiDto[], required: Leads to add (1-100). Each is deduplicated by email within the campaign and provider-detected. Send one element to add a single lead.
    - `email` string, required: Lead email. Only structural validation here (a non-empty string within the length cap) - a malformed address is NOT a request-level 400 but a non-fatal row counted in `summary.invalid`, so one bad address never rejects the whole batch.
    - `firstName` string
    - `lastName` string
    - `companyName` string
    - `jobTitle` string
    - `website` string
    - `linkedinProfile` string
    - `location` string
    - `tags` string[]
    - `customFields` object: Custom fields - a flat map of string/number/boolean values. Each key must be lowercase letters, digits and underscores, starting with a letter, up to 64 characters (e.g. `fund_manager`); a key outside that form is rejected. The number of fields per campaign is capped, and each value is length-limited.
    - `customFieldLabels` object: Display labels for custom-field columns (canonical slug → label). Applied only when a field is first defined on the campaign.
    - `customFieldTypes` object: Data types for custom-field columns (canonical slug → text | url | number | date | image). Applied only when first defined.

## Response `201`

- AddLeadsApiResponseDto
  - `summary` AddLeadsSummaryDto, required
    - `submitted` number, required: Leads submitted in the request.
    - `created` number, required: New leads created.
    - `duplicates` number, required: Skipped as duplicates (already in the campaign).
    - `invalid` number, required: Rejected (invalid or unprocessable).
  - `leads` LeadApiDto[], required: The leads that were created.
    - `id` string, uuid, required
    - `email` string, required
    - `firstName` string, nullable
    - `lastName` string, nullable
    - `companyName` string, nullable
    - `jobTitle` string, nullable
    - `website` string, nullable
    - `linkedinProfile` string, nullable
    - `location` string, nullable
    - `tags` string[], required
    - `customFields` object, required
    - `status` 'not_contacted' | 'scheduled' | 'email_sent' | 'failed' | 'skipped' | 'lead_replied_interested' | 'lead_replied_meeting_request' | 'lead_replied_out_of_office' | 'lead_replied_bounce' | 'lead_replied_wrong_person' | 'lead_replied_not_interested' | 'lead_replied_unsubscribed' | 'lead_replied_uncategorized' | 'lead_converted' | 'lead_lost' | 'blacklisted', required
    - `verification` LeadVerificationView, required
      - `status` string, nullable
      - `subStatus` string, nullable
    - `provider` string, nullable
    - `metrics` LeadMetricsView, required
      - `sent` number, required: Emails sent to the lead (bounced emails included — they left our servers).
      - `opened` number, required: Emails the lead opened, counted once per email. Opens are approximate: Apple Mail and security scanners can add or hide opens.
      - `clicked` number, required: Emails in which the lead clicked a tracked link, counted once per email.
      - `replied` number, required
    - `sequenceProgress` LeadSequenceProgressView
      - `totalSteps` number, required
      - `sentCount` number, required
      - `plannedCount` number, required
      - `failedCount` number, required
      - `nextPlannedAt` string, date-time, nullable: When the next step is scheduled to send; null if none pending.
    - `createdAt` string, date-time, required
    - `lastContactedAt` string, date-time, nullable
    - `lastRepliedAt` string, date-time, nullable
    - `lastOpenedAt` string, date-time, nullable: Latest of the per-email first opens: when the lead first opened the newest email it opened. Re-opening an email does not move it; null if no email was opened.
    - `lastClickedAt` string, date-time, nullable: Latest of the per-email first clicks: when the lead first clicked a tracked link in the newest email it clicked. Repeat clicks do not move it; null if no tracked link was clicked.

## Other responses

- `400`: The request body or parameters failed validation.
- `401`: Missing or invalid API key.
- `402`: A plan limit was reached - top up or upgrade.
- `403`: The key lacks a required scope, or the plan does not include API access.
- `404`: The resource does not exist in your workspace.
- `409`: The request conflicts with current state - e.g. a request with the same Idempotency-Key is still being processed, or the operation partially applied.
- `422`: The Idempotency-Key was already used with a different request body. Use a new key for a new operation.
- `429`: Rate limit exceeded - retry after the interval in the Retry-After header.

---

[API](https://skmtc.dev/mailbeast/apis/mailbeast-public-api.md) · [All operations](https://skmtc.dev/mailbeast/apis/mailbeast-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mailbeast/apis/mailbeast-public-api/revisions/6440ce0738a4?raw)
