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

# Create Lead

> Create a single lead for your campaign

<Note>
  **Endpoint Alias**: You can also use `/api/v1/records` instead of `/api/v1/leads`. Both endpoints are functionally identical - use whichever naming convention fits your integration.
</Note>

## Lead Import Modes

The API supports two lead import patterns depending on your data availability:

<CardGroup cols={2}>
  <Card title="Standard Mode" icon="phone">
    **Phone number known at import time**

    Provide `phoneNumber` directly. The system will call this number when the lead is processed.

    Best for: CRM exports, contact lists, manual imports
  </Card>

  <Card title="Prefetch Mode" icon="database">
    **Phone number fetched just-in-time**

    Provide `externalId` only. The phone number is fetched from your CRM via a predial function before each call.

    Best for: CRM integrations where phone numbers change frequently or require real-time validation
  </Card>
</CardGroup>

<Info>
  **At least one of `phoneNumber` or `externalId` is required.** You can provide both if you want to track the external reference alongside the phone number.
</Info>

## Authentication

<ParamField header="x-api-key" type="string" required>
  Your API key with `write` scope
</ParamField>

## Request Body

<ParamField body="campaignId" type="string" required>
  The ID of the campaign this lead belongs to
</ParamField>

<ParamField body="phoneNumber" type="string">
  Lead's phone number in E.164 format (e.g., +15555551234).

  **Required if `externalId` is not provided.**
</ParamField>

<ParamField body="externalId" type="string">
  Your CRM's internal ID for this lead. Used for deduplication and prefetch lookups.

  **Required if `phoneNumber` is not provided.**
</ParamField>

<ParamField body="metadata" type="object">
  Custom data about the lead (name, company, notes, etc.)
</ParamField>

<ParamField body="scheduledFor" type="string">
  ISO 8601 timestamp for when to call this lead
</ParamField>

<ParamField body="priority" type="number" default="0">
  Lead priority (higher = called first). Range: 0-100
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Whether the request was successful
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="properties">
    <ResponseField name="leadId" type="string">
      The unique ID of the created lead
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="error" type="string | null">
  Error message if request failed
</ResponseField>

## Examples

<Tabs>
  <Tab title="Standard Mode">
    Phone number provided at import time:

    <RequestExample>
      ```bash cURL theme={null}
      curl -X POST https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads \
        -H "x-api-key: YOUR_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "campaignId": "YOUR_CAMPAIGN_ID",
          "phoneNumber": "+15555551234",
          "externalId": "CRM_12345",
          "metadata": {
            "name": "John Doe",
            "company": "Acme Corp"
          },
          "priority": 10
        }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads', {
        method: 'POST',
        headers: {
          'x-api-key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          campaignId: 'YOUR_CAMPAIGN_ID',
          phoneNumber: '+15555551234',
          externalId: 'CRM_12345',
          metadata: {
            name: 'John Doe',
            company: 'Acme Corp'
          },
          priority: 10
        })
      });

      const data = await response.json();
      ```

      ```python Python theme={null}
      import requests

      response = requests.post(
          'https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads',
          headers={
              'x-api-key': 'YOUR_API_KEY',
              'Content-Type': 'application/json'
          },
          json={
              'campaignId': 'YOUR_CAMPAIGN_ID',
              'phoneNumber': '+15555551234',
              'externalId': 'CRM_12345',
              'metadata': {
                  'name': 'John Doe',
                  'company': 'Acme Corp'
              },
              'priority': 10
          }
      )

      print(response.json())
      ```
    </RequestExample>
  </Tab>

  <Tab title="Prefetch Mode">
    External ID only - phone number fetched via predial function:

    <RequestExample>
      ```bash cURL theme={null}
      curl -X POST https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads \
        -H "x-api-key: YOUR_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "campaignId": "YOUR_CAMPAIGN_ID",
          "externalId": "SF_LEAD_12345",
          "metadata": {
            "customer_type": "SF_LEAD",
            "lead_id": "00Q5g00000ABC123"
          },
          "priority": 5
        }'
      ```

      ```javascript JavaScript theme={null}
      const response = await fetch('https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads', {
        method: 'POST',
        headers: {
          'x-api-key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          campaignId: 'YOUR_CAMPAIGN_ID',
          externalId: 'SF_LEAD_12345',
          metadata: {
            customer_type: 'SF_LEAD',
            lead_id: '00Q5g00000ABC123'
          },
          priority: 5
        })
      });

      const data = await response.json();
      ```

      ```python Python theme={null}
      import requests

      response = requests.post(
          'https://YOUR_DEPLOYMENT.lupitor.com/api/v1/leads',
          headers={
              'x-api-key': 'YOUR_API_KEY',
              'Content-Type': 'application/json'
          },
          json={
              'campaignId': 'YOUR_CAMPAIGN_ID',
              'externalId': 'SF_LEAD_12345',
              'metadata': {
                  'customer_type': 'SF_LEAD',
                  'lead_id': '00Q5g00000ABC123'
              },
              'priority': 5
          }
      )

      print(response.json())
      ```
    </RequestExample>
  </Tab>
</Tabs>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "success": true,
    "data": {
      "leadId": "jh7abc123xyz"
    },
    "error": null
  }
  ```

  ```json Error Response theme={null}
  {
    "success": false,
    "data": null,
    "error": "At least one of phoneNumber or externalId is required"
  }
  ```
</ResponseExample>

## Notes

<Warning>
  **Prefetch Mode Requirements**: To use prefetch mode (externalId only), your campaign must have a predial function configured. Contact support to set this up.
</Warning>

<Info>
  **Duplicate Prevention**: Leads are deduplicated by `externalId` first, then by `phoneNumber`. If a lead with the same identifier already exists in the campaign, the request will fail.
</Info>

<Tip>
  **Scheduling**: If you don't provide `scheduledFor`, the lead will be called as soon as possible based on business hours and priority.
</Tip>

<Warning>
  **Phone Format**: When providing a phone number, it must be in E.164 format (+ and country code). Example: `+15555551234`
</Warning>

## Common Errors

| Error                                                   | Cause                       | Solution                                          |
| ------------------------------------------------------- | --------------------------- | ------------------------------------------------- |
| `campaignId is required`                                | Missing campaignId          | Include campaignId in request body                |
| `At least one of phoneNumber or externalId is required` | Neither identifier provided | Include at least one of phoneNumber or externalId |
| `Invalid or inactive API key`                           | Wrong API key               | Check your API key                                |
| `Campaign not found or access denied`                   | Wrong campaign or no access | Verify campaignId and API key scope               |
| `Lead with externalId X already exists`                 | Duplicate externalId        | Lead already exists in campaign                   |
| `Lead with phone number X already exists`               | Duplicate phone             | Lead already exists in campaign                   |
