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

# Bulk Sync Leads

> Create or update leads in bulk from an external system. Each lead is identified by its external `lead_id`. If a lead with the given `lead_id` already exists, it is updated; otherwise a new lead is created.

**Permission:** `leads:sync_create`
**Rate limit:** 50 requests per minute




## OpenAPI

````yaml POST /api/leads/sync
openapi: 3.1.0
info:
  title: Lead Sync API
  description: >
    Bulk lead synchronization endpoints for creating, updating, and deleting
    leads from external systems. These endpoints have stricter rate limits (50
    req/min) compared to standard API endpoints.
  version: 1.0.0
servers:
  - url: https://api.naturalead.ai
    description: Production
  - url: http://localhost:3001
    description: Local development
security:
  - ApiKeyAuth: []
  - BearerAuth: []
paths:
  /api/leads/sync:
    post:
      tags:
        - Lead Sync
      summary: Bulk sync leads
      description: >
        Create or update leads in bulk from an external system. Each lead is
        identified by its external `lead_id`. If a lead with the given `lead_id`
        already exists, it is updated; otherwise a new lead is created.


        **Permission:** `leads:sync_create`

        **Rate limit:** 50 requests per minute
      operationId: bulkSyncLeads
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - leads
              properties:
                leads:
                  type: array
                  description: Array of leads to sync.
                  items:
                    $ref: '#/components/schemas/SyncLead'
      responses:
        '200':
          description: Sync completed successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    description: Total number of leads processed.
                  created:
                    type: integer
                    description: Number of new leads created.
                  updated:
                    type: integer
                    description: Number of existing leads updated.
                  failed:
                    type: integer
                    description: Number of leads that failed to sync.
                  errors:
                    type: array
                    description: Details for each failed lead.
                    items:
                      $ref: '#/components/schemas/SyncError'
        '400':
          description: Invalid request payload.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                properties:
                  error:
                    type: string
                  details:
                    type: object
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                properties:
                  error:
                    type: string
components:
  schemas:
    SyncLead:
      type: object
      description: >
        Only `lead_id` and `phone` are required — leads missing a name or an
        email address are accepted. For the optional fields, omitting a key
        leaves any stored value untouched, while sending `""` or `null` clears
        it.
      required:
        - lead_id
        - phone
      properties:
        lead_id:
          type: string
          maxLength: 255
          description: External unique identifier for the lead.
        name:
          type: string
          maxLength: 500
          nullable: true
          description: >
            Full name of the lead. Optional — a lead without a name is stored as
            unnamed and the AI agent opens the conversation without addressing
            them by name.
        phone:
          type: string
          description: |
            Phone number of the lead, 7-15 digits with an optional leading `+`.
        email:
          type: string
          format: email
          maxLength: 254
          nullable: true
          description: >
            Email address of the lead. Optional — a lead without an email is
            still reachable on WhatsApp and Telegram, but is skipped by email
            campaigns. Must be a valid address when supplied.
        source:
          type: string
          maxLength: 100
          description: >
            Originating system, e.g. `hubspot`. Optional — defaults to `sync`
            for leads created through this endpoint.
        custom_fields:
          type: object
          additionalProperties: true
          description: Arbitrary key-value pairs for custom data.
    SyncError:
      type: object
      properties:
        lead_id:
          type: string
          description: External ID of the lead that failed.
        error:
          type: string
          description: Human-readable error message.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key passed via the `X-API-Key` header.
    BearerAuth:
      type: http
      scheme: bearer
      description: Bearer token passed via the `Authorization` header.

````