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

# Add Campaign Contacts

> Pushes a list of contacts into a campaign, replacing manual CSV uploads. Phone numbers are normalized (Indian formats accepted), duplicates are removed (keeping the longer `person_name`), and any extra keys on a contact are preserved as prompt variables for the agent. Set `enqueue: true` to release the contacts to the agent's calling queue immediately; the agent must have an active outbound trunk configured.



## OpenAPI

````yaml POST /v1/campaigns/{id}/contacts
openapi: 3.1.0
info:
  title: OSVI AI API
  description: REST API for the OSVI AI voice and chat platform
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.osvi.ai
security:
  - ApiToken: []
paths:
  /v1/campaigns/{id}/contacts:
    post:
      summary: Add contacts to a campaign
      description: >-
        Pushes a list of contacts into a campaign, replacing manual CSV uploads.
        Phone numbers are normalized (Indian formats accepted), duplicates are
        removed (keeping the longer `person_name`), and any extra keys on a
        contact are preserved as prompt variables for the agent. Set `enqueue:
        true` to release the contacts to the agent's calling queue immediately;
        the agent must have an active outbound trunk configured.
      parameters:
        - name: id
          in: path
          required: true
          description: The campaign's numeric id.
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agent_uuid
                - contacts
              properties:
                agent_uuid:
                  type: string
                  description: The agent that will place the calls.
                  example: agent_IsZ3Q6Sf_60Eh26XQMGbz-R_og
                contacts:
                  type: array
                  description: >-
                    Up to 10,000 contacts per request. Split larger imports
                    across multiple requests.
                  items:
                    type: object
                    required:
                      - person_name
                      - phone
                    properties:
                      person_name:
                        type: string
                        example: Ravi Kumar
                      phone:
                        type: string
                        description: >-
                          A 10-digit Indian mobile number (starting 6–9) or
                          `+91` followed by 10 digits.
                        example: '9876543210'
                    additionalProperties:
                      type: string
                      description: >-
                        Any extra key is carried through as a prompt variable
                        (e.g. `plan`, `renewal_date`).
                enqueue:
                  type: boolean
                  default: false
                  description: Release the contacts to the calling queue immediately.
                  example: false
            example:
              agent_uuid: agent_IsZ3Q6Sf_60Eh26XQMGbz-R_og
              contacts:
                - person_name: Ravi Kumar
                  phone: '9876543210'
                  plan: Pro
                - person_name: Anita Desai
                  phone: '+919876500000'
              enqueue: true
      responses:
        '201':
          description: Contacts stored (and enqueued when requested).
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      campaign_upload_id:
                        type: integer
                        example: 19
                      contacts_received:
                        type: integer
                        example: 2
                      contacts_accepted:
                        type: integer
                        description: Contacts kept after de-duplication.
                        example: 2
                      duplicates_removed:
                        type: integer
                        example: 0
                      enqueued:
                        type: boolean
                        example: true
                      queued_calls:
                        type: integer
                        description: Present when `enqueued` is true.
                        example: 2
                      dnd_skipped:
                        type: array
                        description: >-
                          Contacts skipped because they are on the DND list
                          (present when any were skipped at enqueue time).
                        items:
                          type: object
        '400':
          description: >-
            A contact failed validation (missing `person_name`, invalid
            `phone`), `contacts` is empty/not an array, or exceeds 10,000
            entries.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBadRequest'
              example:
                success: false
                error: >-
                  contacts[0]: invalid phone. Provide a 10-digit mobile number
                  (starting with 6–9) or +91 followed by 10 digits.
                details: null
        '401':
          description: Invalid or missing API token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorUnauthorized'
        '404':
          description: The campaign or `agent_uuid` is not on your account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorNotFound'
              example:
                success: false
                error: agent_not_found
                details: null
        '422':
          description: '`enqueue` was requested but the agent has no active outbound trunk.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBadRequest'
              example:
                success: false
                error: >-
                  No outbound SIP configuration found for this agent. Please
                  configure an outbound trunk before enqueueing contacts.
                details: null
components:
  schemas:
    ErrorBadRequest:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: max_call_duration_seconds must be between 30 and 1800
        details:
          type: object
          nullable: true
          example: null
    ErrorUnauthorized:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: Invalid API token
    ErrorNotFound:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: agent_not_found
        details:
          type: object
          nullable: true
          example: null
  securitySchemes:
    ApiToken:
      type: apiKey
      in: header
      name: API-Token
      description: >-
        16-character API token associated with your OSVI account. Find it in
        your dashboard under Settings → API.

````