> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yotel.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Leads

> Push single or bulk leads into a campaign for dialing.

Leads are phone numbers (with optional metadata) attached to a campaign.
All leads are automatically scrubbed against the TRAI DNC registry at
ingestion time — leads flagged as DND are marked but not rejected.

## Push a single lead

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.yotel.in/api/v1/campaigns/{campaign_id}/leads \
    -H "Authorization: Bearer yt_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "phone": "9876543210",
      "name": "Priya Sharma",
      "email": "priya@example.com",
      "metadata": {"plan": "enterprise", "source": "website"}
    }'
  ```

  ```python Python theme={null}
  lead = client.leads.create(
      campaign_id="campaign_id",
      phone="9876543210",
      name="Priya Sharma",
      email="priya@example.com",
      metadata={"plan": "enterprise", "source": "website"},
  )
  print(lead.id)
  ```

  ```typescript TypeScript theme={null}
  const lead = await client.leads.create({
    campaign_id: "campaign_id",
    phone: "9876543210",
    name: "Priya Sharma",
    email: "priya@example.com",
    metadata: { plan: "enterprise", source: "website" },
  });
  console.log(lead.id);
  ```
</CodeGroup>

### Request body

| Field      | Type   | Required | Description                                                                           |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| `phone`    | string | Yes      | Indian phone number (10 digits; optional `0` or `91` prefix is stripped). 5–20 chars. |
| `name`     | string | No       | Lead display name                                                                     |
| `email`    | string | No       | Lead email address                                                                    |
| `metadata` | object | No       | Arbitrary key-value pairs passed to webhooks and the voice agent metadata frame       |

**Scope:** `leads:write`  |  **Status:** `201 Created`

<Warning>
  Phone numbers are validated as Indian numbers. International numbers are
  rejected with a `422` validation error.
</Warning>

***

## Bulk push leads

Push up to **500 leads** in a single request. Invalid or duplicate leads
are counted in the response but do not fail the request.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.yotel.in/api/v1/campaigns/{campaign_id}/leads:bulk \
    -H "Authorization: Bearer yt_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "leads": [
        {"phone": "9876543210", "name": "Priya Sharma"},
        {"phone": "9123456789", "name": "Raj Patel"},
        {"phone": "invalid", "name": "Bad Number"}
      ]
    }'
  ```

  ```python Python theme={null}
  result = client.leads.bulk(
      campaign_id="campaign_id",
      leads=[
          {"phone": "9876543210", "name": "Priya Sharma"},
          {"phone": "9123456789", "name": "Raj Patel"},
      ],
  )
  print(f"Added: {result.valid}, Dupes: {result.duplicates}, Invalid: {result.invalid}")
  ```

  ```typescript TypeScript theme={null}
  const result = await client.leads.bulk({
    campaign_id: "campaign_id",
    leads: [
      { phone: "9876543210", name: "Priya Sharma" },
      { phone: "9123456789", name: "Raj Patel" },
    ],
  });
  console.log(`Added: ${result.valid}, Dupes: ${result.duplicates}`);
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "total": 3,
  "valid": 2,
  "invalid": 1,
  "duplicates": 0,
  "results": [
    {"phone": "9876543210", "status": "added", "id": "lead_abc"},
    {"phone": "9123456789", "status": "added", "id": "lead_def"},
    {"phone": "invalid", "status": "invalid", "id": null}
  ]
}
```

**Scope:** `leads:write`  |  **Status:** `200 OK`

| Response field | Type    | Description                                                                    |
| -------------- | ------- | ------------------------------------------------------------------------------ |
| `total`        | integer | Number of leads submitted                                                      |
| `valid`        | integer | Leads successfully added                                                       |
| `invalid`      | integer | Leads that failed phone validation                                             |
| `duplicates`   | integer | Leads already in this campaign (by phone)                                      |
| `results`      | array   | Per-lead outcome with `phone`, `status`, and `id` (null for invalid/duplicate) |

***

## DND scrubbing

Every lead is automatically checked against the TRAI DNC registry at
ingestion. Leads flagged as DND get `dnd_checked: true` and
`dnd_clean: false` — they will **not** be dialed but remain visible in
the campaign for audit. This is a regulatory requirement and cannot be
disabled.

***

## Errors

| Status | Condition                                       |
| ------ | ----------------------------------------------- |
| `404`  | Campaign not found or belongs to another tenant |
| `422`  | Phone number validation failed (single lead)    |
