---
title: "Create or update leads in bulk"
method: POST
path: "/leads"
tags: ["Leads"]
---

# Create or update leads in bulk

`POST /leads`

## Request

- Base URL: `https://api.emailchaser.com/r`
- URL: `https://api.emailchaser.com/r/leads`
- Auth: HTTP bearer

Creates or updates up to 1,000 leads in one request. Leads are matched by email within the workspace. If a lead with that email already exists, it is updated: a field you send with a value is changed, and a field you leave out, or send as null or an empty string, is left as it is. To clear a field, use PUT /leads/{id} with an empty string. middleName is only saved when a lead is created. customVariables, when sent with at least one variable, replaces the lead's whole set; leave it out to keep the set. Every lead needs a valid email: one invalid lead fails the whole request with 400, and nothing is saved. To add the leads to a campaign, pass campaignId at the top level of the request body, not inside a lead. The campaign must have at least one email account attached (POST /campaigns/{id}/sender-emails). If it has none, the leads are saved and added to the campaign, but the call fails with 500; attach an account and send the same request again. count in the response is the number of leads you sent, not the number created. Any attribute outside the named fields can be sent in customVariables and becomes a merge tag usable in email copy. PUT /leads is an alias for this endpoint and behaves identically.

## Request body

- ModelsCreateOrUpdateLeadsRequest
  - `campaignId` integer
  - `leads` ModelsLeadInput[], required
    - `company` string
    - `customVariables` object: CustomVariables holds any attribute the eight named fields do not cover, for example the page a visitor landed on. Each key becomes a merge tag usable in email copy as {key}. Keys are matched case-insensitively with spaces treated as underscores, so "Page Visited" and "page_visited" are the same tag. Values are stored as given; non-string values are rendered with their JSON representation at send time.
    - `email` string, required
    - `firstName` string
    - `lastName` string
    - `linkedin` string
    - `middleName` string: Saved when the lead is created. Not changed when a lead with this email already exists.
    - `phone` string
    - `title` string
    - `website` string

## Response `201`

Leads processed successfully

- ModelsCreateLeadsResponse
  - `count` integer
  - `leads` ModelsCreatedLead[]
    - `email` string
    - `id` integer
  - `message` string

## Other responses

- `400`: Invalid request body, an invalid email, or no leads provided
- `401`: Unauthorized - invalid or missing API key
- `404`: Campaign not found
- `422`: The new leads would go over the plan's contact limit
- `500`: Failed to save the leads, or the campaign has no email account attached

---

[API](https://skmtc.dev/emailchaser/apis/emailchaser-api.md) · [All operations](https://skmtc.dev/emailchaser/apis/emailchaser-api/llms.txt) · [OpenAPI document](https://skmtc.dev/emailchaser/apis/emailchaser-api/revisions/8b114990abb7?raw)
