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

# Add contacts in bulk

> Change up to 100 contact IDs with one Idempotency-Key. Each item is added/removed or skipped with reason not_found (also inaccessible), already_present, not_present, or duplicate. Unknown positive IDs do not reject the batch. Invalid bodies and batches above 100 return 400 invalid_request. Single-contact endpoints are unchanged.



## OpenAPI

````yaml /api/openapi.json post /lists/{id}/contacts
openapi: 3.1.0
info:
  title: PowerDialer API v2
  version: 2.0.0
  description: >-
    Connect your CRM, sales workspace or reporting tools to PowerDialer using
    scoped API keys. Manage contacts and calling lists, read call evidence and
    analytics, and receive signed events. All example records and IDs are
    synthetic; replace them with values from your workspace. Shared-key v1 is
    retired. See /availability for verified release status and historical data
    coverage. Legacy outbound webhooks use a separate contract.
servers:
  - url: https://api.migration.powerdialer.ai/api/public/v2
    description: Production API v2; see /availability for verified release status.
security:
  - ApiKey: []
tags:
  - name: Authentication
  - name: Workspace members
  - name: Contacts
  - name: Calling lists
  - name: Imports
  - name: Calls
  - name: Custom dispositions
  - name: Synchronization
  - name: Analytics
  - name: Webhooks
  - name: Webhook deliveries
  - name: Incoming webhook payloads
  - name: Scheduled calls
    description: Read and manage contact-linked scheduled callbacks.
paths:
  /lists/{id}/contacts:
    post:
      tags:
        - Calling lists
      summary: Add contacts in bulk
      description: >-
        Change up to 100 contact IDs with one Idempotency-Key. Each item is
        added/removed or skipped with reason not_found (also inaccessible),
        already_present, not_present, or duplicate. Unknown positive IDs do not
        reject the batch. Invalid bodies and batches above 100 return 400
        invalid_request. Single-contact endpoints are unchanged.
      operationId: postBulkListMembership
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            minimum: 1
            maximum: 2147483647
          description: >-
            Numeric calling-list ID returned by POST /lists or GET /lists. The
            list must be visible to this credential.
          example: 456
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            pattern: ^[A-Za-z0-9._:-]{1,200}$
          description: >-
            Required. Omitting this header returns 400
            `idempotency_key_required` and changes nothing; a value outside the
            pattern returns 400 `idempotency_key_invalid`. Persist one key for
            this logical operation before sending it. Reuse the same value only
            with the same method, path and body after a timeout. A changed
            request returns 409 idempotency_conflict; a matching retry returns
            the original response.
          example: 9d6b623c-c132-4d2f-b8cf-7c65d4760dbe
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkMembershipWrite'
            example:
              contactIds:
                - 123
                - 124
      responses:
        '200':
          description: >-
            The contact is a member of the list, or the original successful
            attachment response was replayed.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
            RateLimit-Limit:
              schema:
                type: integer
            RateLimit-Remaining:
              schema:
                type: integer
            Idempotency-Replayed:
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                type: object
                properties:
                  added:
                    type: array
                    items:
                      type: integer
                  skipped:
                    type: array
                    items:
                      type: object
                      properties:
                        contactId:
                          type: integer
                        reason:
                          type: string
                          enum:
                            - not_found
                            - already_present
                            - not_present
                            - duplicate
                      required:
                        - contactId
                        - reason
                required:
                  - added
                  - skipped
              example:
                added:
                  - 123
                  - 124
                skipped: []
        default:
          description: >-
            Error. 400 invalid request; 401 invalid credential; 403 insufficient
            access; 404 not found; 409 state/idempotency conflict; 413 size
            limit; 415 body not sent as application/json; 422 verification
            failure; 429 rate limit (Retry-After seconds); 503 temporary service
            failure.
          headers:
            Retry-After:
              schema:
                type: integer
            X-Request-Id:
              schema:
                type: string
                format: uuid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: invalid_api_key
                  message: API key is invalid, expired or revoked
                  requestId: 00000000-0000-4000-8000-000000000004
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >-
            # Replace example resource IDs and ownerId with values from your
            workspace.

            : "${POWERDIALER_API_KEY:?Set POWERDIALER_API_KEY to your scoped API
            key}"

            # Set this once per operation; reuse it with the same request after
            a timeout.

            : "${POWERDIALER_REQUEST_ID:?Set POWERDIALER_REQUEST_ID to a new
            UUID for this operation}"

            curl --request POST \
              --url 'https://api.migration.powerdialer.ai/api/public/v2/lists/456/contacts' \
              --header "Authorization: Bearer $POWERDIALER_API_KEY" \
              --header "Idempotency-Key: $POWERDIALER_REQUEST_ID" \
              --header 'Content-Type: application/json' \
              --data '{
              "contactIds": [
                123,
                124
              ]
            }'
components:
  schemas:
    BulkMembershipWrite:
      type: object
      properties:
        contactIds:
          type: array
          minItems: 1
          maxItems: 100
          items:
            type: integer
            minimum: 1
            maximum: 2147483647
      required:
        - contactIds
      additionalProperties: false
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable machine-readable error code.
            message:
              type: string
              description: Human-readable explanation.
            requestId:
              type: string
              format: uuid
              description: Request identifier to include when investigating a failure.
            details:
              type: array
              items:
                type: object
                properties:
                  path:
                    type: string
                    description: >-
                      Where the request failed, prefixed by location: `body`,
                      `body.<field>`, `query.<name>` or `path.<name>`. A
                      root-level problem reports its location alone, for example
                      `body` when no JSON object was sent, so a missing body is
                      never confused with a missing field or header.
                  message:
                    type: string
                required:
                  - path
                  - message
              description: >-
                Validation errors, when available. Each `path` names the part of
                the request that failed.
          required:
            - code
            - message
            - requestId
      required:
        - error
      examples:
        - error:
            code: insufficient_scope
            message: Requires contacts:read
            requestId: 00000000-0000-4000-8000-000000000004
        - error:
            code: invalid_request
            message: 'Request validation failed: body.url: Invalid url'
            requestId: 00000000-0000-4000-8000-000000000004
            details:
              - path: body.url
                message: Invalid url
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      bearerFormat: pd_<live|test>_<credential UUID>.<random secret>
      description: >-
        Issued in Developers. Workspace/owner/scopes come from credential, never
        acting-user headers. API keys cannot manage API credentials.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.